26 #include <Classes.hpp>
27 #include <Controls.hpp>
28 #include <StdCtrls.hpp>
30 #include <Buttons.hpp>
31 #include <ExtCtrls.hpp>
33 #include <Dialogs.hpp>
34 #include <Graphics.hpp>
35 #include <ComCtrls.hpp>
52 #pragma package(smart_init)
71 TTrain::TTrain(
int Caller,
int RearStartElementIn,
int RearStartExitPosIn, AnsiString InputCode,
int StartSpeedIn,
int MassIn,
double MaxRunningSpeedIn,
72 double MaxBrakeRateIn,
double PowerAtRailIn,
TTrainMode TrainModeIn,
TTrainDataEntry *TrainDataEntryPtrIn,
int RepeatNumberIn,
int IncrementalMinutesIn,
73 int IncrementalDigitsIn,
int SignallerMaxSpeedIn) : RearStartElement(RearStartElementIn), RearStartExitPos(RearStartExitPosIn), HeadCode(InputCode),
74 StartSpeed(StartSpeedIn), Mass(MassIn), MaxRunningSpeed(MaxRunningSpeedIn), MaxBrakeRate(MaxBrakeRateIn), PowerAtRail(PowerAtRailIn),
75 TrainMode(TrainModeIn), TrainDataEntryPtr(TrainDataEntryPtrIn), RepeatNumber(RepeatNumberIn), IncrementalMinutes(IncrementalMinutesIn),
76 IncrementalDigits(IncrementalDigitsIn), SignallerMaxSpeed(SignallerMaxSpeedIn)
87 AnsiString(RearStartExitPosIn) +
"," + AnsiString(InputCode) +
"," + AnsiString(StartSpeedIn) +
"," + AnsiString(MassIn) +
"," +
88 AnsiString(TrainModeIn));
132 for(
int x = 0; x < 4; x++)
141 for(
int x = 0; x < 4; x++)
150 for(
int x = 0; x < 4; x++)
155 for(
int x = 0; x < 4; x++)
159 for(
int x = 0; x < 3; x++)
196 for(
int x = 0; x < 4; x++)
250 throw Exception(
"Error in attempting to delete FrontCodePtr");
254 for(
int x = 0; x < 4; x++)
258 throw Exception(
"Error in attempting to delete BackgroundPtr[" + AnsiString(x) +
"]");
263 for(
int x = 0; x < 4; x++)
267 throw Exception(
"Error in attempting to delete HeadCodeGrPtr[" + AnsiString(x) +
"]");
296 int NextElementPosition, NextEntryPos, ElementLength, SpeedLimit;
362 bool TempDerail =
false;
408 else if((NextElementPosition > -1) && (NextEntryPos > -1))
479 throw Exception(
"Error, LeadElement Exit Connection is NotSet");
489 for(
int x = 0; x < 4; x++)
496 for(
int x = 0; x < 4; x++)
739 if((random(RandRange)) == 0)
756 int LockedVectorNumber;
995 if(BufferLocation ==
"")
1000 if((BufferLocation ==
"") || (BufferLocation != ExpectedLocation))
1062 int NextElementPosition, NextEntryPos;
1086 NextElementPosition = -1;
1089 if((NextElementPosition > -1) && (NextEntryPos > -1))
1207 AnsiString StationName;
1218 throw Exception(
"Error - Stopped at through station but neither lead nor mid elements have a name");
1231 if((NextElementPosition > -1) && (NextEntryPos > -1))
1357 if(TIFEntryPos == 0)
1393 if(NextElementPosition > -1)
1430 AnsiString Loc =
"";
1431 bool LocNamed =
false;
1460 Loc =
"outside railway";
1492 NextElementPosition = -1;
1503 if((NextElementPosition > -1) && (NextEntryPos > -1) && !
SPADFlag)
1521 if((NextElementPosition > -1) && (NextEntryPos > -1))
1559 FirstPair.second).
GetELink() == TempELink))
1564 SecondPair.second).
GetELink() == TempELink))
1578 FirstPair.second).
GetELink() == TempELink))
1583 SecondPair.second).
GetELink() == TempELink))
1597 FirstPair.second).
GetELink() == TempELink))
1602 SecondPair.second).
GetELink() == TempELink))
1632 ContinuationAutoSigEntry.
RouteNumber = RouteNumber;
1635 int NewLastElement = 0, NewLastExitPos = 0;
1653 if(NewLastElement == -1)
1656 throw Exception(
"Error, Connection = -1 in Continuation loop in UpdateTrain");
1659 if(NewLastExitPos == -1)
1661 throw Exception(
"Error, ConnLinkPos = -1 in Continuation loop in UpdateTrain");
1663 LastElement = NewLastElement;
1664 LastExitPos = NewLastExitPos;
1667 if(CumDistance < 1200)
1673 int FirstDistance = 0;
1674 if(CumDistance >= 1200)
1676 FirstDistance = 100;
1680 FirstDistance = 1200 - CumDistance;
1682 if(FirstDistance < 100)
1684 FirstDistance = 100;
1710 if(VectorIT->RouteNumber == RouteNumber)
1757 LockedVectorNumber)))
1916 for(
int x = 0; x < 4; x++)
1923 for(
int x = 0; x < 4; x++)
1949 if((LeadElementTrainID > -1) && (LeadElementTrainID !=
TrainID))
1954 if(OtherTrainEntryPos == -1)
1956 throw Exception(
"Error - OtherTrainEntryPos not set");
1975 int OtherTrainID = -1;
1976 if((MidExitLinkNum == 1) || (MidExitLinkNum == 3) || (MidExitLinkNum == 7) || (MidExitLinkNum == 9))
2067 bool StopRequired =
false;
2080 int NextElementEntryPos = -1;
2081 int NextElementExitPos = -1;
2082 bool TrainOnNextElement =
false;
2083 bool StopSignalAtNextElement =
false;
2084 if(ForwardConnection)
2092 StopSignalAtNextElement = ((NextTrackElement.
Config[NextElementExitPos] ==
Signal) && (NextTrackElement.
Attribute == 0));
2094 if(TrainAtStopLinkPos1 || TrainAtStopLinkPos2 || (ForwardConnection && (TrainOnNextElement || StopSignalAtNextElement)))
2149 throw Exception(
"Error, Straddle shouldn't be LeadMid prior to resetting at exit from UpdateTrain");
2362 if(Code.Length() != 4)
2366 for(
int x = 1; x < 5; x++)
2373 for(
int x = 0; x < 4; x++)
2537 throw Exception(
"Error in GetOffsetValues - Link value wrong");
2550 if((EntryLink == 1) || (EntryLink == 2) || (EntryLink == 4) || (EntryLink == 7))
2565 AnsiString(
VOffset) +
"," + AnsiString(Element) +
"," + AnsiString(EntryPos) +
"," +
HeadCode);
2574 TRect SourceRect, DestRect;
2576 DestRect.init(0, 0, 8, 8);
2579 Graphics::TBitmap *TempGraphic =
new Graphics::TBitmap;
2581 TempGraphic->PixelFormat = pf8bit;
2582 TempGraphic->Width = 16;
2583 TempGraphic->Height = 16;
2589 TempGraphic->Transparent =
true;
2593 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2594 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2600 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2608 else if(TempElement.
SpeedTag == 89)
2612 else if(TempElement.
SpeedTag == 90)
2616 else if(TempElement.
SpeedTag == 91)
2620 else if(TempElement.
SpeedTag == 92)
2624 else if(TempElement.
SpeedTag == 93)
2628 else if(TempElement.
SpeedTag == 94)
2632 else if(TempElement.
SpeedTag == 95)
2636 TempGraphic->Transparent =
true;
2640 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2641 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2643 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2650 for(
int x = 0; x < 40; x++)
2665 TempGraphic->Transparent =
true;
2669 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2670 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2672 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2686 TempGraphic->Transparent =
true;
2690 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2691 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2695 TempGraphic->Canvas->Draw(0, 0, TempElement.
GraphicPtr);
2698 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2703 TempGraphic->Transparent =
true;
2707 int BDVectorPos = -1;
2716 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2721 TempGraphic->Transparent =
true;
2725 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2726 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2728 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2734 TempGraphic->Transparent =
true;
2738 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2739 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2741 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
3007 throw Exception(
"Error, same train on two different bridge tracks");
3053 AnsiString(EntryPos) +
"," +
HeadCode);
3070 throw Exception(
"Error, TrackVectorPosition set but not EntryPos in SetTrainElementID");
3089 AnsiString(EntryPos) +
"," +
HeadCode);
3098 throw Exception(
"Error, TrackVectorPosition set but not EntryPos in ResetTrainElementID");
3131 AnsiString(ElementEntryPos) +
"," + AnsiString(
HOffset) +
"," + AnsiString(
VOffset) +
"," + AnsiString(StraddleValue) +
"," +
HeadCode);
3132 int LockedVectorNumber;
3145 TRect SourceRect, DestRect;
3146 DestRect.init(0, 0, 8, 8);
3153 int FirstELink, SecondELink = -1;
3156 if(RoutePair2.first > -1)
3165 if(SecondELink == -1)
3167 throw Exception(
"Error - Second ELink should be set but isn't in PlotAlternativeTrackRouteGraphic [1]");
3172 throw Exception(
"Error - First & Second ELinks have same value in PlotAlternativeTrackRouteGraphic");
3182 Graphics::TBitmap *DestGraphic =
new Graphics::TBitmap;
3183 DestGraphic->PixelFormat = pf8bit;
3184 DestGraphic->Width = 8;
3185 DestGraphic->Height = 8;
3186 DestGraphic->Transparent =
true;
3189 DestGraphic->Canvas->CopyRect(DestRect, RouteElement.
GetRouteEXGraphicPtr()->Canvas, SourceRect);
3198 PrefDirElement, LockedVectorNumber))
3213 if(ElementEntryPos > 1)
3235 AnsiString(EntryPos) +
"," +
HeadCode);
3237 bool WrongRoute =
false;
3263 int LinkNumber = TrackElement.
Link[EntryPos];
3264 if((LinkNumber == 1) || (LinkNumber == 3) || (LinkNumber == 7) || (LinkNumber == 9))
3269 bool LogActionErrorCalled =
false;
3279 LogActionErrorCalled =
true;
3296 else if(LinkNumber == 3)
3304 LogActionErrorCalled =
true;
3321 else if(LinkNumber == 7)
3329 LogActionErrorCalled =
true;
3346 else if(LinkNumber == 9)
3354 LogActionErrorCalled =
true;
3386 else if((RouteElement.
GetELinkPos() == 2) && (EntryPos == 0) && PointsAtElement)
3391 else if((RouteElement.
GetELinkPos() == 0) && (EntryPos == 2) && PointsAtElement)
3401 else if((RouteElement.
GetXLinkPos() == 2) && (EntryPos == 0) && PointsAtElement)
3406 else if((RouteElement.
GetXLinkPos() == 0) && (EntryPos == 2) && PointsAtElement)
3415 throw Exception(
"Error, Element in route but no route found in CheckAndCancelRouteForWrongEndEntry");
3436 bool ColourError =
false, ColourError2 =
false;
3441 ColourError2 =
true;
3443 for(
int x = 0; x < 4; x++)
3448 ColourError2 =
true;
3454 "ERROR: Colour depth insufficient to display train colours properly. Please ensure that the 'safe' (web) palette of 256 colours can be displayed");
3458 for(
int x = 0; x < 4; x++)
3545 AnsiString(EntryPos) +
"," +
HeadCode);
3546 int EntryHalfLength, CurrentElementHalfLength, NextElementHalfLength, CumulativeLength = 0, CurrentTrackVectorPosition = TrackVectorPosition;
3547 int DistanceAtHalfBraking, DistanceAtThreeQuarterBraking, ExitPos, NextTrackVectorPosition, NextEntryPos;
3548 bool RedSignalFlag =
false, BuffersFlag =
false, StationFlag =
false, BuffersOrContinuationNowFlag =
false, ContinuationNextFlag =
false,
3549 TrainInFrontInSignallerModeFlag =
false;
3550 double LimitingSpeed, FrontElementMaxSpeed, MaxExitSpeedAtHalfBrakingSquared, MaxExitSpeedAtHalfBraking, NextSpeedLimit, TempBrakeRate;
3551 double ExitSpeedHalfSquared, ExitSpeedFullSquared;
3552 bool SignallerStopRequired =
false;
3563 if(CurrentTrackVectorPosition > -1)
3567 if((EntryPos == 0) || (EntryPos == 2))
3580 else if(EntryPos == 1)
3604 EntryHalfLength = CurrentElementHalfLength;
3609 throw Exception(
"Error - CurrentTrackVectorPosition < 0 in SetTrainMovementValues");
3613 throw Exception(
"Error - HalfLength or SpeedLimit < 0 in SetTrainMovementValues");
3660 FrontElementMaxSpeed = LimitingSpeed;
3695 double ExitSpeedAtMaxBraking;
3700 ExitSpeedAtMaxBraking = 0;
3710 if(ExitSpeedAtMaxBraking > LimitingSpeed)
3712 SpeedToUse = ExitSpeedAtMaxBraking;
3716 SpeedToUse = LimitingSpeed;
3731 RedSignalFlag =
false;
3732 BuffersFlag =
false;
3733 StationFlag =
false;
3734 BuffersOrContinuationNowFlag =
false;
3735 ContinuationNextFlag =
false;
3738 CumulativeLength += (2 * CurrentElementHalfLength);
3741 SignallerStopRequired =
true;
3763 bool StopRequired =
false;
3777 StationFlag =
false;
3783 BuffersOrContinuationNowFlag =
true;
3785 if(!BuffersOrContinuationNowFlag && !BuffersFlag && !StationFlag)
3789 if((EntryPos == 0) || (EntryPos == 2))
3811 if(NextTrackVectorPosition > -1)
3816 if((NextEntryPos == 0) || (NextEntryPos == 2))
3829 else if(NextEntryPos == 1)
3842 if(NextEntryPos > 1)
3856 throw Exception(
"Error - Trying to access NextTrackVectorPosition when none present in SetTrainMovementValues");
3868 RedSignalFlag =
true;
3890 TrainInFrontInSignallerModeFlag =
true;
3914 if(RedSignalFlag || BuffersFlag || StationFlag || TrainInFrontInSignallerModeFlag || SignallerStopRequired ||
StepForwardFlag)
3926 double MaxHalfSpeed;
3930 if(MaxHalfSpeedAtHalfBraking > FrontElementMaxSpeed)
3932 MaxHalfSpeed = FrontElementMaxSpeed;
3936 MaxHalfSpeed = MaxHalfSpeedAtHalfBraking;
3944 bool HalfSpeedLimited =
false;
3948 HalfSpeedLimited =
true;
3978 if(HalfSpeedLimited)
4003 if(SignallerStopRequired)
4019 int TempMaxExitSpeed;
4022 if(MaxExitSpeedAtHalfBrakingSquared < 10)
4024 MaxExitSpeedAtHalfBraking = 0;
4028 MaxExitSpeedAtHalfBraking = sqrt(MaxExitSpeedAtHalfBrakingSquared);
4032 if(MaxExitSpeedAtHalfBraking > FrontElementMaxSpeed)
4034 TempMaxExitSpeed = FrontElementMaxSpeed;
4038 TempMaxExitSpeed = MaxExitSpeedAtHalfBraking;
4050 if(ExitSpeedHalfSquared < 10)
4060 if(ExitSpeedFullSquared < 10)
4132 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
4133 ExitTimeFull =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
4157 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
4158 ExitTimeHalf =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
4168 if(!BuffersOrContinuationNowFlag)
4170 if(NextSpeedLimit < LimitingSpeed)
4172 LimitingSpeed = NextSpeedLimit;
4176 int TempMaxExitSpeed;
4180 if(MaxExitSpeedAtHalfBrakingSquared < 10)
4182 MaxExitSpeedAtHalfBraking = 0;
4186 MaxExitSpeedAtHalfBraking = sqrt(MaxExitSpeedAtHalfBrakingSquared);
4188 if(MaxExitSpeedAtHalfBraking > FrontElementMaxSpeed)
4190 TempMaxExitSpeed = FrontElementMaxSpeed;
4194 TempMaxExitSpeed = MaxExitSpeedAtHalfBraking;
4205 TempBrakeRate = ((
EntrySpeed *
EntrySpeed) - (LimitingSpeed * LimitingSpeed)) / 3.6 / 3.6 / 2 / CumulativeLength;
4218 if(!BuffersOrContinuationNowFlag)
4220 CurrentTrackVectorPosition = NextTrackVectorPosition;
4221 EntryPos = NextEntryPos;
4222 CurrentElementHalfLength = NextElementHalfLength;
4225 ContinuationNextFlag =
true;
4229 while(((CumulativeLength -
FrontElementLength) < DistanceAtHalfBraking) && ((!BuffersOrContinuationNowFlag && !ContinuationNextFlag) ||
4249 if(ExitSpeedHalfSquared < 10)
4259 if(ExitSpeedFullSquared < 10)
4322 double DeltaExitTimeToMaxInSecs;
4323 double DistanceToMax;
4332 DeltaExitTimeToMaxInSecs = 2 * EntryHalfLength * 3.6 /
EntrySpeed;
4334 DistanceToMax = EntryHalfLength;
4337 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
4338 ExitTimeFull =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
4355 double DeltaExitTimeToMaxInSecs;
4356 double DistanceToMax;
4365 DeltaExitTimeToMaxInSecs = 2 * EntryHalfLength * 3.6 /
EntrySpeed;
4367 DistanceToMax = EntryHalfLength / 2;
4370 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
4371 ExitTimeHalf =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
4382 if(ExitSpeedHalfSquared < 10)
4392 if(ExitSpeedFullSquared < 10)
4411 if((EntryPos == 0) || (EntryPos == 2))
4433 if(NextTrackVectorPosition > -1)
4435 int NextElementLength;
4436 if(NextEntryPos > 1)
4444 double NextStoppingSpeed = sqrt(3.6 * 3.6 * 2 *
BrakeRate * NextElementLength);
4580 if((Ptr->Command ==
"cdt") || (Ptr->FormatType ==
Repeat))
4584 if((Ptr->ArrivalTime > TDateTime(-1)) && (Ptr->LocationName == Name))
4593 if((Ptr->EventTime > TDateTime(-1)) && (Ptr->LocationName == Name) && (Ptr->Command ==
"pas"))
4618 int CurrentTrackVectorPosition =
LeadElement, NextTrackVectorPosition;
4636 CurrentTrackVectorPosition).
Attribute != 4))
4675 if((EntryPos == 0) || (EntryPos == 2))
4697 CurrentTrackVectorPosition = NextTrackVectorPosition;
4698 EntryPos = NextEntryPos;
4722 throw Exception(
"Error - failed to set ReturnVal in ClearToNextSignal()");
4747 bool PlatformFoundFlag =
false, StopRequired =
false, SkipRouteCheck =
false, RouteOrPartRouteSet =
false;
4748 int CurrentTrackVectorPosition =
LeadElement, NextTrackVectorPosition, ElementNumber = 0, Distance = 0;
4749 int RouteStartPosition;
4751 int PlatformPosition;
4753 int EntryPos =
LeadEntryPos, ExitPos, NextEntryPos, RouteID;
4769 if(Distance > (4000 + LeadElementDistance))
4792 if(OtherTrain.
LeadElement == CurrentTrackVectorPosition)
4795 if((OtherCommand ==
"Fjo") || (OtherCommand ==
"jbo") || (OtherCommand ==
"cdt") || (OtherCommand ==
"Frh") ||
4841 if(!PlatformFoundFlag)
4843 PlatformPosition = CurrentTrackVectorPosition;
4846 PlatformFoundFlag =
true;
4862 if((EntryPos == 0) || (EntryPos == 2))
4906 if(ElementNumber < 2)
4908 SkipRouteCheck =
true;
4912 SkipRouteCheck =
false;
4914 if(ElementNumber == 1)
4916 RouteStartPosition = CurrentTrackVectorPosition;
4926 if(ElementNumber > 1)
4930 RouteOrPartRouteSet =
true;
4934 RouteOrPartRouteSet =
false;
4937 if(!SkipRouteCheck && !RouteOrPartRouteSet)
4944 int ExitLink = CurrentTrackElement.
Link[ExitPos];
4945 if((ExitLink == 1) || (ExitLink == 3) || (ExitLink == 7) || (ExitLink == 9))
4957 Distance += CurrentTrackElement.
Length01;
4961 Distance += CurrentTrackElement.
Length23;
4963 NextTrackVectorPosition = CurrentTrackElement.
Conn[ExitPos];
4964 NextEntryPos = CurrentTrackElement.
ConnLinkPos[ExitPos];
4965 CurrentTrackVectorPosition = NextTrackVectorPosition;
4966 EntryPos = NextEntryPos;
5003 return(RepeatHeadCode);
5025 bool FrontValid =
false, RearValid =
false;
5026 TTrackElement FrontAdjacentTrackElement, RearAdjacentTrackElement;
5030 TrainToBeJoinedBy = NULL;
5044 int TrainToBeJoinedByID = -1;
5065 if((TrainToBeJoinedByID < 0) && RearValid)
5084 if(TrainToBeJoinedByID < 0)
5086 TrainToBeJoinedBy = NULL;
5091 if(!TrainToBeJoinedBy->
Stopped())
5093 TrainToBeJoinedBy = NULL;
5104 TDateTime TimetableNonRepeatTime,
bool Warning)
5139 AnsiString(ActionType) +
"," + LocationName +
"," +
HeadCode);
5140 AnsiString BaseLog =
"", WarningBaseLog =
"", PerfLog =
"", ActionLog =
"";
5141 int IntMinsLate = 0;
5146 ActionLog =
" arrived at ";
5155 ActionLog =
" terminated at ";
5160 ActionLog =
" departed from ";
5162 if(ActionType ==
Pass)
5164 ActionLog =
" passed ";
5168 ActionLog =
" created at ";
5170 if(ActionType ==
Enter)
5172 ActionLog =
" entered railway at ";
5174 if(ActionType ==
Leave)
5176 ActionLog =
" left railway at ";
5180 ActionLog =
" split from front to ";
5184 ActionLog =
" split from rear to ";
5188 ActionLog =
" joined by ";
5192 ActionLog =
" changed direction at ";
5196 ActionLog =
" became new service ";
5200 ActionLog =
" taken under signaller control at ";
5204 ActionLog =
" restored to timetable control at ";
5210 ActionLog =
" REMOVED FROM RAILWAY DUE TO CRASH at ";
5214 ActionLog =
" REMOVED FROM RAILWAY DUE TO DERAILMENT at ";
5218 ActionLog =
" REMOVED FROM RAILWAY at ";
5223 ActionLog =
" received signaller authority to proceed";
5227 ActionLog =
" received signaller authority to step forward";
5231 ActionLog =
" changed direction under signaller control at ";
5235 ActionLog =
" received signaller authority to pass red signal";
5239 ActionLog =
" received signaller instruction to stop";
5243 ActionLog =
" stopped on signaller instruction ";
5247 ActionLog =
" joined under signaller control by ";
5251 ActionLog =
" suffered an onboard power failure at ";
5255 ActionLog =
" failure repaired at ";
5259 ActionLog =
" left railway under signaller control at ";
5261 if(OtherHeadCode !=
"")
5263 OtherHeadCode +=
" at ";
5270 WarningBaseLog =
HeadCode + ActionLog + OtherHeadCode + LocationName;
5276 bool TimePerformance =
true;
5284 TimePerformance =
false;
5288 double MinsLate = ((double)(ActualTime -
GetTrainTime(1, TimetableNonRepeatTime))) * 1440;
5290 if(ActionType ==
Pass)
5304 IntMinsLate = int(ceil(MinsLate));
5308 IntMinsLate = int(floor(MinsLate));
5310 if(IntMinsLate == 0)
5312 PerfLog =
" on time";
5314 else if(IntMinsLate == 1)
5316 PerfLog =
" 1 minute late";
5318 else if(IntMinsLate == -1)
5320 PerfLog =
" 1 minute early";
5322 else if(IntMinsLate > 1)
5324 PerfLog =
" " + AnsiString(IntMinsLate) +
" minutes late";
5326 else if(IntMinsLate < -1)
5328 int PosIntMinsLate = -IntMinsLate;
5329 PerfLog =
" " + AnsiString(PosIntMinsLate) +
" minutes early";
5331 if(LocationName.Pos(
'-') > 0)
5333 PerfLog =
"," + PerfLog;
5347 if((ActionType ==
Arrive) && (IntMinsLate == 0))
5351 else if((ActionType ==
Arrive) && (IntMinsLate > 0))
5356 else if((ActionType ==
Arrive) && (IntMinsLate < 0))
5362 else if((ActionType ==
Pass) && (IntMinsLate == 0))
5366 else if((ActionType ==
Pass) && (IntMinsLate > 0))
5371 else if((ActionType ==
Pass) && (IntMinsLate < 0))
5377 else if((ActionType ==
Leave) && (IntMinsLate == 0))
5381 else if((ActionType ==
Leave) && (IntMinsLate > 0))
5386 else if((ActionType ==
Leave) && (IntMinsLate < 0))
5392 else if((ActionType ==
Depart) && (IntMinsLate == 0))
5396 else if((ActionType ==
Depart) && (IntMinsLate > 0))
5415 AnsiString LocName =
"";
5482 if(LocationName ==
"")
5486 int FirstNamedElementPos, SecondNamedElementPos, FirstNamedLinkedElementPos, SecondNamedLinkedElementPos;
5487 int RearTrainRearPosition, RearTrainFrontPosition, RearTrainExitPos;
5488 int FrontTrainRearPosition, FrontTrainFrontPosition, FrontTrainExitPos;
5492 if(LocationName !=
"")
5500 SecondNamedElementPos, FirstNamedLinkedElementPos, SecondNamedLinkedElementPos))
5505 SecondNamedElementPos, FirstNamedLinkedElementPos, SecondNamedLinkedElementPos))
5519 int LeadPosA = FirstNamedElementPos;
5520 int LeadPosB = FirstNamedLinkedElementPos;
5521 int LeadPosC = SecondNamedElementPos;
5522 int LeadPosD = SecondNamedLinkedElementPos;
5524 int LeadNumAtLoc = 0;
5541 if(LeadNumAtLoc < 4)
5545 SecondNamedLinkedElementPos))
5547 FirstNamedElementPos = LeadPosA;
5548 FirstNamedLinkedElementPos = LeadPosB;
5549 SecondNamedElementPos = LeadPosC;
5550 SecondNamedLinkedElementPos = LeadPosD;
5554 int MidNumAtLoc = 0;
5571 if(LeadNumAtLoc > MidNumAtLoc)
5574 FirstNamedElementPos = LeadPosA;
5575 FirstNamedLinkedElementPos = LeadPosB;
5576 SecondNamedElementPos = LeadPosC;
5577 SecondNamedLinkedElementPos = LeadPosD;
5591 throw Exception(
"Error - LocationName not set in FrontTrainSplit");
5601 FrontTrainFrontPosition = FirstNamedLinkedElementPos;
5602 FrontTrainRearPosition = FirstNamedElementPos;
5603 RearTrainFrontPosition = SecondNamedElementPos;
5604 RearTrainRearPosition = SecondNamedLinkedElementPos;
5608 FrontTrainFrontPosition = SecondNamedLinkedElementPos;
5609 FrontTrainRearPosition = SecondNamedElementPos;
5610 RearTrainFrontPosition = FirstNamedElementPos;
5611 RearTrainRearPosition = FirstNamedLinkedElementPos;
5618 FrontTrainFrontPosition = SecondNamedLinkedElementPos;
5619 FrontTrainRearPosition = SecondNamedElementPos;
5620 RearTrainFrontPosition = FirstNamedElementPos;
5621 RearTrainRearPosition = FirstNamedLinkedElementPos;
5625 FrontTrainFrontPosition = FirstNamedLinkedElementPos;
5626 FrontTrainRearPosition = FirstNamedElementPos;
5627 RearTrainFrontPosition = SecondNamedElementPos;
5628 RearTrainRearPosition = SecondNamedLinkedElementPos;
5631 RearTrainExitPos = -1;
5632 for(
int x = 0; x < 4; x++)
5636 RearTrainExitPos = x;
5640 if(RearTrainExitPos == -1)
5642 throw Exception(
"Error - RearTrainRearPosition not linked to RearTrainFrontPosition in FrontTrainSplit");
5644 FrontTrainExitPos = -1;
5645 for(
int x = 0; x < 4; x++)
5649 FrontTrainExitPos = x;
5653 if(FrontTrainExitPos == -1)
5655 throw Exception(
"Error - FrontTrainRearPosition not linked to FrontTrainFrontPosition in FrontTrainSplit");
5658 int TrainIDOnRearOfRearTrain, TrainIDOnFrontOfRearTrain, TrainIDOnRearOfFrontTrain, TrainIDOnFrontOfFrontTrain;
5665 else if((RearMostElement.
TrackType ==
Bridge) && (RearTrainExitPos < 2))
5685 else if((FrontMostElement.
TrackType ==
Bridge) && (FrontTrainExitPos < 2))
5693 if(((TrainIDOnRearOfRearTrain > -1) && (TrainIDOnRearOfRearTrain !=
TrainID)) || ((TrainIDOnFrontOfRearTrain > -1) && (TrainIDOnFrontOfRearTrain !=
TrainID)
5694 ) || ((TrainIDOnRearOfFrontTrain > -1) && (TrainIDOnRearOfFrontTrain !=
TrainID)) ||
5695 ((TrainIDOnFrontOfFrontTrain > -1) && (TrainIDOnFrontOfFrontTrain !=
TrainID)))
5792 if(LocationName ==
"")
5796 int FirstNamedElementPos, SecondNamedElementPos, FirstNamedLinkedElementPos, SecondNamedLinkedElementPos;
5797 int RearTrainRearPosition, RearTrainFrontPosition, RearTrainExitPos;
5798 int FrontTrainRearPosition, FrontTrainFrontPosition, FrontTrainExitPos;
5802 if(LocationName !=
"")
5809 SecondNamedLinkedElementPos))
5813 SecondNamedLinkedElementPos))
5827 int LeadPosA = FirstNamedElementPos;
5828 int LeadPosB = FirstNamedLinkedElementPos;
5829 int LeadPosC = SecondNamedElementPos;
5830 int LeadPosD = SecondNamedLinkedElementPos;
5832 int LeadNumAtLoc = 0;
5849 if(LeadNumAtLoc < 4)
5853 SecondNamedLinkedElementPos))
5855 FirstNamedElementPos = LeadPosA;
5856 FirstNamedLinkedElementPos = LeadPosB;
5857 SecondNamedElementPos = LeadPosC;
5858 SecondNamedLinkedElementPos = LeadPosD;
5862 int MidNumAtLoc = 0;
5879 if(LeadNumAtLoc > MidNumAtLoc)
5882 FirstNamedElementPos = LeadPosA;
5883 FirstNamedLinkedElementPos = LeadPosB;
5884 SecondNamedElementPos = LeadPosC;
5885 SecondNamedLinkedElementPos = LeadPosD;
5899 throw Exception(
"Error - LocationName not set in RearTrainSplit");
5909 FrontTrainFrontPosition = FirstNamedLinkedElementPos;
5910 FrontTrainRearPosition = FirstNamedElementPos;
5911 RearTrainFrontPosition = SecondNamedElementPos;
5912 RearTrainRearPosition = SecondNamedLinkedElementPos;
5916 FrontTrainFrontPosition = SecondNamedLinkedElementPos;
5917 FrontTrainRearPosition = SecondNamedElementPos;
5918 RearTrainFrontPosition = FirstNamedElementPos;
5919 RearTrainRearPosition = FirstNamedLinkedElementPos;
5926 FrontTrainFrontPosition = SecondNamedLinkedElementPos;
5927 FrontTrainRearPosition = SecondNamedElementPos;
5928 RearTrainFrontPosition = FirstNamedElementPos;
5929 RearTrainRearPosition = FirstNamedLinkedElementPos;
5933 FrontTrainFrontPosition = FirstNamedLinkedElementPos;
5934 FrontTrainRearPosition = FirstNamedElementPos;
5935 RearTrainFrontPosition = SecondNamedElementPos;
5936 RearTrainRearPosition = SecondNamedLinkedElementPos;
5939 RearTrainExitPos = -1;
5940 for(
int x = 0; x < 4; x++)
5944 RearTrainExitPos = x;
5948 if(RearTrainExitPos == -1)
5950 throw Exception(
"Error - RearTrainRearPosition not linked to RearTrainFrontPosition in RearTrainSplit");
5952 FrontTrainExitPos = -1;
5953 for(
int x = 0; x < 4; x++)
5957 FrontTrainExitPos = x;
5961 if(FrontTrainExitPos == -1)
5963 throw Exception(
"Error - FrontTrainRearPosition not linked to FrontTrainFrontPosition in RearTrainSplit");
5966 int TrainIDOnRearOfRearTrain, TrainIDOnFrontOfRearTrain, TrainIDOnRearOfFrontTrain, TrainIDOnFrontOfFrontTrain;
5973 else if((RearMostElement.
TrackType ==
Bridge) && (RearTrainExitPos < 2))
5993 else if((FrontMostElement.
TrackType ==
Bridge) && (FrontTrainExitPos < 2))
6001 if(((TrainIDOnRearOfRearTrain > -1) && (TrainIDOnRearOfRearTrain !=
TrainID)) || ((TrainIDOnFrontOfRearTrain > -1) && (TrainIDOnFrontOfRearTrain !=
TrainID)
6002 ) || ((TrainIDOnRearOfFrontTrain > -1) && (TrainIDOnRearOfFrontTrain !=
TrainID)) ||
6003 ((TrainIDOnFrontOfFrontTrain > -1) && (TrainIDOnFrontOfFrontTrain !=
TrainID)))
6142 TTrain *TrainToBeJoinedBy;
6175 double OtherBrakeForce = TrainToBeJoinedBy->
MaxBrakeRate * TrainToBeJoinedBy->
Mass;
6177 double CombinedBrakeRate = (OtherBrakeForce + OwnBrakeForce) / (TrainToBeJoinedBy->
Mass +
Mass);
6234 int RouteNumber = -1;
6242 bool FirstPass =
true;
6247 if(FirstPass && (TVPos2 != FirstRouteElementVecPos))
6350 for(
int x = 0; x < IncNum; x++)
6383 else if(Ptr->
Command ==
"jbo")
6394 throw Exception(
"Error - illegal command in SendMissedActionLogs for IncNum = " + AnsiString(IncNum) +
", and command = " + Ptr->
Command);
6400 bool IncludeFER =
false;
6408 if(!IncludeFER && (Ptr->
Command ==
"Fer"))
6413 else if(IncludeFER && (Ptr->
Command ==
"Fer"))
6424 else if(Ptr->
Command ==
"Fjo")
6430 else if(Ptr->
Command ==
"Frh")
6440 else if(Ptr->
Command ==
"Frh-sh")
6491 else if(Ptr->
Command ==
"jbo")
6496 else if(Ptr->
Command ==
"cdt")
6504 throw Exception(
"Error - illegal command in SendMissedActionLogs for IncNum = " + AnsiString(IncNum) +
", and command = " + Ptr->
Command);
6876 int RouteNumber = -1;
6884 bool FirstPass =
true;
6889 if(FirstPass && (TVPos2 != FirstRouteElementVecPos))
6917 ",FloatingLabelNextString" +
"," +
HeadCode);
6918 AnsiString RetStr =
"", LocationName =
"";
6922 throw Exception(
"Error - start entry in FloatingLabelNextString");
6962 else if(Ptr->
Command ==
"Fns")
6968 else if(Ptr->
Command ==
"F-nshs")
6999 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7001 else if(Ptr->
Command ==
"Frh")
7003 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7005 else if(Ptr->
Command ==
"Fer")
7007 AnsiString AllowedExits =
"";
7010 else if(Ptr->
Command ==
"Fjo")
7015 else if(Ptr->
Command ==
"jbo")
7020 else if(Ptr->
Command ==
"fsp")
7025 else if(Ptr->
Command ==
"rsp")
7030 else if(Ptr->
Command ==
"cdt")
7043 + AnsiString(RptNum) +
",CheckNewServiceDepartureTime," +
HeadCode);
7044 AnsiString DepTime =
"", EventTime =
"";
7045 bool CDTFlag =
false;
7049 if(AVI->Command ==
"cdt")
7054 if((AVI->Command ==
"fsp") || (AVI->Command ==
"rsp"))
7057 RetStr +=
"\nNew service splits at " + EventTime;
7061 if(AVI->Command ==
"jbo")
7064 RetStr +=
"\nNew service joined by " + AVI->OtherHeadCode +
" at " + EventTime;
7068 if((AVI->FormatType ==
TimeLoc) && (AVI->DepartureTime > TDateTime(-1)))
7073 RetStr +=
"\nNew service changes direction then departs at " + DepTime;
7077 RetStr +=
"\nNew service departs at " + DepTime;
7094 ",FloatingTimetableString" +
"," +
HeadCode);
7095 AnsiString RetStr =
"", PartStr =
"";
7097 bool SkipDep =
false, SkipDepActedOn =
false;
7103 throw Exception(
"Error - start entry in FloatingTimetableString");
7106 bool FirstPass =
true;
7119 AnsiString TrainLoc =
"";
7165 AnsiString TrainLoc =
"";
7201 else if(Ptr->
Command ==
"Fns")
7207 else if(Ptr->
Command ==
"F-nshs")
7240 else if(Ptr->
Command ==
"Frh")
7244 else if(Ptr->
Command ==
"Fer")
7246 AnsiString AllowedExits =
"";
7249 else if(Ptr->
Command ==
"Fjo")
7254 else if(Ptr->
Command ==
"jbo")
7259 else if(Ptr->
Command ==
"fsp")
7264 else if(Ptr->
Command ==
"rsp")
7269 else if(Ptr->
Command ==
"cdt")
7275 RetStr = RetStr +
'\n' + PartStr;
7289 SkipDepActedOn =
true;
7300 RetStr =
"Timetable finished";
7304 RetStr =
"No timetable";
7461 bool ForwardHeadCode;
7465 ForwardHeadCode =
true;
7470 ForwardHeadCode =
false;
7613 if(ColourNumber == 0)
7617 else if(ColourNumber == 1)
7621 else if(ColourNumber == 2)
7625 else if(ColourNumber == 3)
7629 else if(ColourNumber == 4)
7633 else if(ColourNumber == 5)
7637 else if(ColourNumber == 6)
7641 else if(ColourNumber == 7)
7645 else if(ColourNumber == 8)
7649 else if(ColourNumber == 9)
7653 else if(ColourNumber == 10)
7657 else if(ColourNumber == 11)
7661 else if(ColourNumber == 12)
7665 else if(ColourNumber == 13)
7669 else if(ColourNumber == 14)
7681 for(
int x = 0; x < 4; x++)
7688 for(
int x = 0; x < 4; x++)
7773 if((LocationAndMarker[1] !=
'*') && (LocationAndMarker.Length() > 6))
7776 AnsiString Location = LocationAndMarker.SubString(1, LocationAndMarker.Length() - 6);
7777 bool GiveMessagesFalse =
false;
7778 bool CheckLocationsExistInRailwayTrue =
true;
7785 AnsiString Marker = LocationAndMarker.SubString(LocationAndMarker.Length() - 5, 6);
7788 if(Marker[6] ==
'1')
8253 bool HideFlashingTrain =
true;
8256 Graphics::TBitmap *SmallTrainBitmap;
8297 HideFlashingTrain =
false;
8302 HideFlashingTrain =
false;
8307 HideFlashingTrain =
false;
8312 HideFlashingTrain =
false;
8317 HideFlashingTrain =
false;
8321 if((
LeadElement > -1) && (!HideFlashingTrain || Flash))
8325 if((
MidElement > -1) && (!HideFlashingTrain || Flash))
8349 for(
int y = 0; y < 3; y++)
8353 bool FoundFlag =
false;
8364 if(IMPair.first != IMPair.second)
8391 if((LocationName ==
"") && (
MidElement > -1))
8395 if((LocationName ==
"") && (
LagElement > -1))
8399 if(LocationName ==
"")
8401 throw Exception(
"Error - Location name not set in TrainAtLocation");
8412 for(
int x = 0; x < 4; x++)
8424 for(
int x = 0; x < 4; x++)
8441 AnsiString(LinkNumber) +
"," +
HeadCode);
8493 int DistanceToRedSignal = 0, DistanceToExit = -1;
8494 float TimeToAct = 0, LastTimeToExit =
TimeToExit;
8498 float MinsEarly = 0;
8499 TDateTime DepartureTime;
8500 TDateTime ArrivalTime;
8526 if(TempTTE < LastTimeToExit)
8554 if(TempTTE < LastTimeToExit)
8570 if(TempTTE < LastTimeToExit)
8592 if(TempTTE < LastTimeToExit)
8608 if(TempTTE < LastTimeToExit)
8646 float CurrentStopTime;
8647 float LaterStopTime;
8648 float RecoverableTime;
8656 if((DistanceToRedSignal == -1) && (DistanceToExit == -1))
8663 bool DistanceToRedSignalSet = (DistanceToRedSignal > -1);
8664 bool DistanceToExitSet = (DistanceToExit > -1);
8665 int GenericDistance = DistanceToRedSignal;
8666 if(DistanceToExitSet)
8668 GenericDistance = DistanceToExit;
8684 float TimeToSubtract, TotalStopTime;
8687 TimeToSubtract = RecoverableTime;
8730 if(CurrentStopTime > 0)
8732 TotalStopTime = CurrentStopTime + LaterStopTime;
8741 else if((MinsEarly > 0) && !
Stopped())
8743 TotalStopTime = LaterStopTime + MinsEarly;
8747 if(LaterStopTime == 0)
8749 TotalStopTime = CurrentStopTime;
8755 TotalStopTime = CurrentStopTime + LaterStopTime - TimeToSubtract;
8758 if(AvTrackSpeed < 30)
8762 int Speed = AvTrackSpeed;
8772 if(DistanceToRedSignalSet)
8774 TimeToAct = TotalStopTime + GenericDistance * 3.6 / 60 / Speed;
8784 TimeToExit = TotalStopTime + GenericDistance * 3.6 / 60 / Speed;
8807 if((NextEntryPos == 0) || (NextEntryPos == 2))
8934 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
8977 int IncrementalMinutes = 0;
8978 int IncrementalDigits = 0;
8986 throw Exception(
"Error - Repeat entry && less than two trains for Snt entry: " + TDEntry.
HeadCode);
9021 if(AVEntry0.
Command ==
"Snt-sh")
9026 int IncrementalMinutes = 0;
9027 int IncrementalDigits = 0;
9035 throw Exception(
"Error - Repeat entry && less than two trains for Snt-sh entry: " + TDEntry.
HeadCode);
9067 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
9127 AnsiString Loc =
"";
9128 bool ElementFound =
false;
9133 ElementFound =
true;
9138 ElementFound =
true;
9143 ElementFound =
true;
9172 else if(AVEntryPtr->
Command ==
"Fer")
9174 bool CorrectExit =
false;
9284 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
9299 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
9314 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
9325 bool TTrainController::AddTrain(
int Caller,
int RearPosition,
int FrontPosition, AnsiString HeadCode,
int StartSpeed,
int Mass,
double MaxRunningSpeed,
9326 double MaxBrakeRate,
double PowerAtRail, AnsiString ModeStr,
TTrainDataEntry *TrainDataEntryPtr,
int RepeatNumber,
int IncrementalMinutes,
9327 int IncrementalDigits,
int SignallerSpeed,
bool SignallerControl,
TActionEventType &EventType)
9329 LogEvent(AnsiString(Caller) +
",AddTrain," + AnsiString(RearPosition) +
"," + AnsiString(FrontPosition) +
"," + HeadCode +
"," + AnsiString(StartSpeed) +
9330 "," + AnsiString(Mass) +
"," + ModeStr);
9332 "," + HeadCode +
"," + AnsiString(StartSpeed) +
"," + AnsiString(Mass) +
"," + ModeStr +
"," + HeadCode);
9334 int RearExitPos = -1;
9336 for(
int x = 0; x < 4; x++)
9343 if(RearExitPos == -1)
9345 throw Exception(
"Error, RearExit == -1 in AddTrain");
9347 bool ReportFlag =
true;
9364 if(ModeStr ==
"Timetable")
9370 if(MaxRunningSpeed < 10)
9372 MaxRunningSpeed = 10;
9374 if(SignallerSpeed < 10)
9376 SignallerSpeed = 10;
9378 TTrain *NewTrain =
new TTrain(0, RearPosition, RearExitPos, HeadCode, StartSpeed, Mass, MaxRunningSpeed, MaxBrakeRate, PowerAtRail, TrainMode,
9379 TrainDataEntryPtr, RepeatNumber, IncrementalMinutes, IncrementalDigits, SignallerSpeed);
9384 if(SignallerControl)
9414 if(!SignallerControl)
9429 if(!SignallerControl)
9440 AnsiString Loc =
"";
9457 if(!SignallerControl)
9476 int RouteNumber = -1;
9477 bool SignalsSet =
false;
9484 int RouteStartPosition;
9488 if(FirstPair.first == RouteNumber)
9490 RouteStartPosition = FirstPair.second;
9492 else if(SecondPair.first == RouteNumber)
9494 RouteStartPosition = SecondPair.second;
9498 throw Exception(
"Error, RouteNumber not found in Route2MultiMap in 1st of 2 calls to SetAllRearwardsSignals in AddTrain");
9504 else if(RouteNumber > -1)
9524 int LinkedRouteNumber = -1;
9545 int RouteStartPosition;
9549 if(FirstPair.first == RouteNumber)
9551 RouteStartPosition = FirstPair.second;
9553 else if(SecondPair.first == RouteNumber)
9555 RouteStartPosition = SecondPair.second;
9559 throw Exception(
"Error, RouteNumber not found in Route2MultiMap in 2nd of 2 calls to SetAllRearwardsSignals in AddTrain");
9565 else if(RouteNumber > -1)
9585 int LinkedRouteNumber = -1;
9606 AnsiString(TrackVectorNumber));
9609 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
9618 throw Exception(
"Error, VecPos not set in EntryPos");
9620 if(
TrainVectorAt(2, VecPos).LeadElement == TrackVectorNumber)
9625 else if(
TrainVectorAt(4, VecPos).MidElement == TrackVectorNumber)
9630 else if(
TrainVectorAt(6, VecPos).LagElement == TrackVectorNumber)
9644 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
9652 throw Exception(
"Error - No Train identified in TrainVectorAtIdent with ID = " + AnsiString(TrainID));
9662 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
9692 AnsiString RetStr =
"", PartStr =
"";
9700 if((Ptr->Command !=
"") && (Ptr->Command[1] ==
'S'))
9708 if(Ptr->SignallerControl)
9710 RetStr =
"Train under signaller control";
9715 if(Ptr->ArrivalTime == Ptr->DepartureTime)
9726 else if((Ptr->FormatType ==
TimeLoc) && (Ptr->ArrivalTime != TDateTime(-1)))
9730 else if((Ptr->FormatType ==
TimeLoc) && (Ptr->ArrivalTime == TDateTime(-1)))
9734 else if(Ptr->FormatType ==
PassTime)
9738 else if(Ptr->Command ==
"Fns")
9744 else if(Ptr->Command ==
"F-nshs")
9747 Ptr->NonRepeatingShuttleLinkHeadCode +
" at " + Ptr->LocationName;
9754 else if((Ptr->Command ==
"Fns-sh") && (RepNum < (TTDEPtr->
NumberOfTrains - 1)))
9761 else if((Ptr->Command ==
"Fns-sh") && (RepNum >= (TTDEPtr->
NumberOfTrains - 1)))
9764 Ptr->NonRepeatingShuttleLinkHeadCode, +
" at " + Ptr->LocationName;
9767 else if((Ptr->Command ==
"Frh-sh") && (RepNum < (TTDEPtr->
NumberOfTrains - 1)))
9774 else if((Ptr->Command ==
"Frh-sh") && (RepNum >= (TTDEPtr->
NumberOfTrains - 1)))
9776 PartStr =
"Terminate at " + Ptr->LocationName;
9778 else if(Ptr->Command ==
"Frh")
9780 PartStr =
"Terminate at " + Ptr->LocationName;
9782 else if(Ptr->Command ==
"Fer")
9784 AnsiString AllowedExits;
9788 else if(Ptr->Command ==
"Fjo")
9791 Ptr->OtherHeadCode, RepNum, IncDig) +
" at " + Ptr->LocationName;
9793 else if(Ptr->Command ==
"jbo")
9796 (50, Ptr->OtherHeadCode, RepNum, IncDig) +
" at " + Ptr->LocationName;
9798 else if(Ptr->Command ==
"fsp")
9803 else if(Ptr->Command ==
"rsp")
9808 else if(Ptr->Command ==
"cdt")
9814 RetStr = RetStr +
'\n' + PartStr;
9822 while(Ptr < TTDEPtr->ActionVector.end() && (Count < 33) && ((Ptr->Command ==
"") || ((Ptr->Command !=
"") && (Ptr->Command[1] !=
'F'))));
9835 + AnsiString(RptNum) +
",ControllerCheckNewServiceDepartureTime," + TDEPtr->
HeadCode);
9836 AnsiString DepTime =
"", EventTime =
"";
9837 bool CDTFlag =
false;
9841 if(AVI->Command ==
"cdt")
9846 if((AVI->Command ==
"fsp") || (AVI->Command ==
"rsp"))
9849 RetStr +=
"\nNew service splits at " + EventTime;
9853 if(AVI->Command ==
"jbo")
9856 RetStr +=
"\nNew service joined by " + AVI->OtherHeadCode +
" at " + EventTime;
9860 if((AVI->FormatType ==
TimeLoc) && (AVI->DepartureTime > TDateTime(-1)))
9865 RetStr +=
"\nNew service changes direction then departs at " + DepTime;
9869 RetStr +=
"\nNew service departs at " + DepTime;
10029 ActiveTrackElementNameMapEntry.second = 0;
10035 std::ifstream TTBLFile(FileName, std::ios_base::binary);
10038 if(TTBLFile.is_open())
10040 char *TrainTimetableString =
new char[10000];
10042 bool EndOfFile =
false;
10045 TTBLFile.getline(TrainTimetableString, 10000,
'\0');
10047 if(TTBLFile.eof() && (TrainTimetableString[0] ==
'\0'))
10054 delete[] TrainTimetableString;
10058 AnsiString OneLine(TrainTimetableString);
10059 bool FinalCallFalse =
false;
10060 while((Count == 0) && !
ProcessOneTimetableLine(5, Count, OneLine, EndOfFile, FinalCallFalse, GiveMessages, CheckLocationsExistInRailway))
10064 TTBLFile.getline(TrainTimetableString, 10000,
'\0');
10065 if(TTBLFile.eof() && (TrainTimetableString[0] ==
'\0'))
10070 TimetableMessage(GiveMessages,
"Timetable invalid - unable to find a valid start time on its own line");
10072 delete[] TrainTimetableString;
10076 OneLine = AnsiString(TrainTimetableString);
10082 TTBLFile.getline(TrainTimetableString, 10000,
'\0');
10084 if(TTBLFile.eof() && (TrainTimetableString[0] ==
'\0'))
10094 OneLine = AnsiString(TrainTimetableString);
10096 if(OneLine.Length() > 9999)
10098 TimetableMessage(GiveMessages,
"Timetable contains a line that is too long - 10,000 or more characters!");
10100 delete[] TrainTimetableString;
10104 bool FinalCallFalse =
false;
10105 if(!
ProcessOneTimetableLine(6, Count, OneLine, EndOfFile, FinalCallFalse, GiveMessages, CheckLocationsExistInRailway))
10109 delete[] TrainTimetableString;
10113 if(EndOfFile && (Count < 2))
10116 TimetableMessage(GiveMessages,
"Timetable has too few or no relevant entries - must have a start time on its own line and at least one train");
10118 delete[] TrainTimetableString;
10124 delete[] TrainTimetableString;
10129 TimetableMessage(GiveMessages,
"Failed to open timetable file, make sure it's spelled correctly, it exists and isn't open in another application");
10140 bool CheckLocationsExistInRailway)
10265 AnsiString((
short)FinalCall) +
"," + AnsiString((
short)CheckLocationsExistInRailway));
10275 if(OneLine[1] !=
'*')
10277 int SCPos = OneLine.Pos(
';');
10288 bool AllCommas =
true;
10290 for(
int x = 1; x < OneLine.Length() + 1; x++)
10292 if(OneLine[x] !=
',')
10297 if(AllCommas || (OneLine ==
""))
10312 AnsiString First =
"", Second =
"", Third =
"", Fourth =
"";
10313 int RearStartOrRepeatMins = 0, FrontStartOrRepeatDigits = 0, NumberOfRepeats = 0;
10314 TDateTime EventTime(0), ArrivalTime(0), DepartureTime(0);
10315 TDateTime StartTime(0);
10317 bool Warning =
false;
10344 AnsiString TrainInfoStr =
"", HeadCode =
"", Description =
"";
10345 int StartSpeed = 0, MaxRunningSpeed = 0, Mass = 0;
10346 double MaxBrakeRate = 0;
10347 double PowerAtRail = 0;
10348 int SignallerSpeed = 0;
10349 if(OneLine[1] ==
'*')
10355 int Pos = OneLine.Pos(
',');
10358 int SubStringLength = 20;
10359 if(OneLine.Length() < 20)
10361 SubStringLength = OneLine.Length();
10363 TimetableMessage(GiveMessages,
"Error in timetable - entry incomplete: see '" + OneLine.SubString(1, SubStringLength) +
"'....");
10367 TrainInfoStr = OneLine.SubString(1, Pos - 1);
10368 if(!
SplitTrainInfo(0, TrainInfoStr, HeadCode, Description, StartSpeed, MaxRunningSpeed, Mass, MaxBrakeRate, PowerAtRail, SignallerSpeed,
10378 TempTrainDataEntry.
HeadCode = HeadCode;
10382 TempTrainDataEntry.
Mass = Mass;
10390 AnsiString NewRemainder = OneLine.SubString(Pos + 1, OneLine.Length() - Pos);
10393 while(NewRemainder[NewRemainder.Length()] ==
',')
10395 if(NewRemainder.Length() > 1)
10397 NewRemainder = NewRemainder.SubString(1, NewRemainder.Length() - 1);
10406 if(NewRemainder ==
"")
10408 TimetableMessage(GiveMessages,
"Error in timetable - no events following train: '" + OneLine +
"'");
10413 int CommaCount = 0;
10414 for(
int x = 1; x < NewRemainder.Length() + 1; x++)
10416 if(NewRemainder[x] ==
',')
10421 if(CommaCount == 0)
10423 if((NewRemainder.SubString(7, 3) !=
"Snt") || (NewRemainder[NewRemainder.Length()] !=
'S'))
10425 int SubStringLength = 20;
10426 if(OneLine.Length() < 20)
10428 SubStringLength = OneLine.Length();
10431 "Error in timetable - must have at least a start and a finish event for a train that is not started under signaller control - see line beginning: '" +
10432 OneLine.SubString(1, SubStringLength) +
"'....");
10437 AnsiString OneEntry =
"";
10442 bool FinishFlag =
false;
10443 for(
int x = 0; x < CommaCount + 1; x++)
10445 if((CommaCount == 0) || (x < CommaCount))
10450 if(CommaCount == 0)
10452 OneEntry = NewRemainder;
10457 Pos = NewRemainder.Pos(
',');
10458 OneEntry = NewRemainder.SubString(1, Pos - 1);
10459 NewRemainder = NewRemainder.SubString(Pos + 1, NewRemainder.Length() - Pos);
10465 RearStartOrRepeatMins = 0;
10466 FrontStartOrRepeatDigits = 0;
10467 NumberOfRepeats = 0;
10468 if(!
SplitEntry(0, OneEntry, GiveMessages, CheckLocationsExistInRailway, First, Second, Third, Fourth, RearStartOrRepeatMins,
10469 FrontStartOrRepeatDigits, FormatType, LocationType, SequenceType, ShuttleLinkType, ExitList, Warning))
10471 TimetableMessage(GiveMessages,
"Error in timetable - Event: '" + OneEntry +
"'");
10476 if(Warning && (Second ==
"Frh"))
10478 TimetableMessage(GiveMessages,
"Error in line - '" + OneEntry +
"': warnings cannot be given for 'Frh' events");
10482 if(Warning && (Second ==
"Fjo"))
10485 "': warnings cannot be given for 'Fjo' events, for a train join warning add a 'W' prefix to the 'jbo' event");
10491 if(SequenceType !=
Start)
10493 TimetableMessage(GiveMessages,
"Error in timetable - First event not a start event: '" + OneEntry +
"'");
10497 if((Second ==
"Snt") && (Fourth ==
'S') && (NewRemainder !=
""))
10499 if(NewRemainder[1] !=
'R')
10502 "Error in timetable - the only event that can follow a train created under signaller control is a repeat, see '" +
10508 if((Second ==
"Snt") || (Second ==
"Snt-sh"))
10512 if((HeadCode ==
"") || (Description ==
"") || (MaxRunningSpeed == 0) || (Mass == 0) || (MaxBrakeRate == 0))
10515 TimetableMessage(GiveMessages,
"Error in timetable - train information incomplete before 'Snt' or 'Snt-sh' start event: '" +
10521 if((Second ==
"Sfs") || (Second ==
"Sns") || (Second ==
"Sns-sh") || (Second ==
"Sns-fsh"))
10526 TimetableMessage(GiveMessages,
"Error in timetable - headcode missing before 'Sfs', 'Sns', 'Sns-sh' or 'Sns-fsh' start event: '" +
10531 if((StartSpeed != 0) || (MaxRunningSpeed != 0) || (Mass != 0) || (MaxBrakeRate != 0) || (PowerAtRail != 0))
10534 "Error in timetable - information additional to a headcode & optional description given before 'Sfs', 'Sns', 'Sns-sh' or 'Sns-fsh' start event: '" +
10541 if(SequenceType ==
Finish)
10550 TDateTime TempTime;
10556 ActionVectorEntry.
Warning = Warning;
10572 ActionVectorEntry.
Command = Second;
10587 else if(FormatType ==
TimeCmd)
10593 ActionVectorEntry.
Command = Second;
10601 ActionVectorEntry.
Command = Second;
10602 ActionVectorEntry.
ExitList = ExitList;
10610 ActionVectorEntry.
Command = Second;
10624 ActionVectorEntry.
Command = Second;
10635 ActionVectorEntry.
Command = Second;
10645 ActionVectorEntry.
Command = Second;
10654 ActionVectorEntry.
Command = Second;
10663 ActionVectorEntry.
Command = Second;
10669 ActionVectorEntry.
Command = Second;
10671 TempTrainDataEntry.
ActionVector.push_back(ActionVectorEntry);
10676 OneEntry = NewRemainder;
10681 RearStartOrRepeatMins = 0;
10682 FrontStartOrRepeatDigits = 0;
10683 NumberOfRepeats = 0;
10684 if((FinishFlag) && (OneEntry[1] !=
'R'))
10687 TimetableMessage(GiveMessages,
"Error in timetable - Last event = '" + OneEntry +
"'. An earlier finish event has been found with something other than a repeat following it - only a repeat can follow a finish event.");
10691 if(OneEntry[1] !=
'R')
10693 if(!
SplitEntry(1, OneEntry, GiveMessages, CheckLocationsExistInRailway, First, Second, Third, Fourth, RearStartOrRepeatMins,
10694 FrontStartOrRepeatDigits, FormatType, LocationType, SequenceType, ShuttleLinkType, ExitList, Warning))
10696 TimetableMessage(GiveMessages,
"Error in timetable - Event: '" + OneEntry +
"'");
10700 if(SequenceType !=
Finish)
10702 TimetableMessage(GiveMessages,
"Error in timetable - last event should be a finish: '" + OneEntry +
"'");
10709 TDateTime TempTime;
10715 ActionVectorEntry.
Warning = Warning;
10722 ActionVectorEntry.
Command = Second;
10730 ActionVectorEntry.
Command = Second;
10739 ActionVectorEntry.
Command = Second;
10748 ActionVectorEntry.
Command = Second;
10758 ActionVectorEntry.
Command = Second;
10759 ActionVectorEntry.
ExitList = ExitList;
10763 ActionVectorEntry.
Command = Second;
10765 TempTrainDataEntry.
ActionVector.push_back(ActionVectorEntry);
10770 if(!
SplitRepeat(0, OneEntry, RearStartOrRepeatMins, FrontStartOrRepeatDigits, NumberOfRepeats, GiveMessages))
10786 TempTrainDataEntry.
ActionVector.push_back(ActionVectorEntry);
10805 if((HeadCode[HeadCode.Length() - 1] <
'0') || (HeadCode[HeadCode.Length() - 1] >
'9'))
10810 if((HeadCode[HeadCode.Length()] <
'0') || (HeadCode[HeadCode.Length()] >
'9'))
10825 if(TimeStr.Length() < 5)
10830 if((TimeStr[1] <
'0') || (TimeStr[1] >
'9'))
10835 if((TimeStr[2] <
'0') || (TimeStr[2] >
'9'))
10840 if(TimeStr[3] !=
':')
10845 if((TimeStr[4] <
'0') || (TimeStr[4] >
'5'))
10850 if((TimeStr[5] <
'0') || (TimeStr[5] >
'9'))
10855 while(TimeStr.Length() > 5)
10857 TimeStr = TimeStr.SubString(1, TimeStr.Length() - 1);
10859 double WholeHours = (AnsiString(TimeStr[1]) + AnsiString(TimeStr[2])).ToDouble();
10860 double FracHour = ((AnsiString(TimeStr[4]) + AnsiString(TimeStr[5])).ToDouble()) / 60.0;
10862 if((WholeHours + FracHour) >= 95.98334)
10867 Time = TDateTime((WholeHours + FracHour) / 24);
10874 bool TTrainController::SplitEntry(
int Caller, AnsiString OneEntry,
bool GiveMessages,
bool CheckLocationsExistInRailway, AnsiString &First, AnsiString &Second,
10875 AnsiString &Third, AnsiString &Fourth,
int &RearStartOrRepeatMins,
int &FrontStartOrRepeatDigits,
TTimetableFormatType &FormatType,
10884 TDateTime TempTime;
10886 if(OneEntry.Length() > 0)
10888 if(OneEntry[1] ==
'W')
10891 OneEntry = OneEntry.SubString(2, OneEntry.Length() - 1);
10895 if(OneEntry ==
"Frh")
10905 if(OneEntry.Length() < 7)
10910 int Pos = OneEntry.Pos(
';');
10918 First = OneEntry.SubString(1, 5);
10924 AnsiString Remainder = OneEntry.SubString(Pos + 1, OneEntry.Length() - Pos);
10926 if((Remainder[1] >=
'0') && (Remainder[1] <=
'9'))
10929 if(Remainder.Length() < 7)
10934 Pos = Remainder.Pos(
';');
10941 Second = Remainder.SubString(1, 5);
10947 Third = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
10960 Pos = Remainder.Pos(
';');
10963 Second = Remainder;
10964 if(Second ==
"cdt")
10989 if((Pos != 4) && (Pos != 7) && (Pos != 8))
10995 Second = Remainder.SubString(1, Pos - 1);
10997 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
10999 Pos = Remainder.Pos(
';');
11006 Third = Remainder.SubString(1, Pos - 1);
11007 Fourth = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
11009 if((Second ==
"Snt") || (Second ==
"Snt-sh"))
11012 int SpacePos = Third.Pos(
' ');
11018 AnsiString RearStartStr = Third.SubString(1, SpacePos - 1);
11019 AnsiString FrontStartStr = Third.SubString(SpacePos + 1, Third.Length() - SpacePos);
11021 if(CheckLocationsExistInRailway)
11031 if(Second ==
"Snt")
11034 SequenceType =
Start;
11043 SequenceType =
Start;
11054 if(Second ==
"Sns-sh")
11058 SequenceType =
Start;
11073 if(Second ==
"F-nshs")
11087 if(Second ==
"Sns-fsh")
11091 SequenceType =
Start;
11101 if(Second ==
"Fns-sh")
11121 if(Second ==
"pas")
11136 if(Second ==
"Fer")
11143 if(CheckLocationsExistInRailway)
11155 if((Second !=
"Fns") && (Second !=
"Fjo") && (Second !=
"jbo") && (Second !=
"fsp") && (Second !=
"rsp") && (Second !=
"Sfs") && (Second !=
"Sns") &&
11156 (Second !=
"Frh-sh"))
11168 if(Second ==
"Frh-sh")
11176 if((Second ==
"Fns") || (Second ==
"Fjo") || (Second ==
"Frh-sh"))
11180 if((Second ==
"jbo") || (Second ==
"fsp") || (Second ==
"rsp"))
11184 if((Second ==
"Sfs") || (Second ==
"Sns"))
11186 SequenceType =
Start;
11204 if((LocStr[1] >=
'0') && (LocStr[1] <=
'9'))
11209 for(
int x = 1; x < LocStr.Length() + 1; x++)
11211 if(LocStr[x] <
' ')
11216 if(LocStr[x] >
'z')
11223 if(CheckLocationsExistInRailway)
11228 "' appears in the timetable but is not a valid name. To be valid the name must be a stopping location and apply to one or more platforms " +
11229 "(not concourses on their own), or to track at a blue non-station named location. BUT NOTE THAT trains can't stop at continuations so a name " +
11230 "that includes a continuation will not be valid.");
11248 if((HeadCode.Length() < 4) || (HeadCode.Length() > 8))
11251 "', length must be between 4 and 8 characters, and last 4 must be a legitimate headcode. This error can also be caused by omitting a service reference after Sns, Snt-sh, Sns-sh, Fns, Fns-sh or Frh-sh");
11256 for(
int x = 1; x < (HeadCode.Length() + 1); x++)
11258 if((HeadCode[x] <
' ') || (HeadCode[x] >
'~'))
11260 TimetableMessage(GiveMessages,
"Non-printable character in headcode '" + HeadCode +
"'");
11266 for(
int x = 3; x >= 0; x--)
11268 if(((HeadCode[HeadCode.Length() - x] <
'A') || (HeadCode[HeadCode.Length() - x] >
'Z')) && ((HeadCode[HeadCode.Length() - x] <
'a') ||
11269 (HeadCode[HeadCode.Length() - x] >
'z')) && ((HeadCode[HeadCode.Length() - x] <
'0') || (HeadCode[HeadCode.Length() - x] >
'9')))
11271 TimetableMessage(GiveMessages,
"Headcode error in '" + HeadCode +
"', headcode must consist of letters and digits only");
11287 AnsiString CurrentID =
"";
11289 if(IDSet.Length() == 0)
11291 TimetableMessage(GiveMessages,
"Must have at least one exit element ID following 'Fer'");
11295 for(
int x = 1; x <= IDSet.Length(); x++)
11298 if(((C <
'0') || (C >
'9')) && (C !=
' ') && (C !=
'N') && (C !=
'-'))
11300 TimetableMessage(GiveMessages,
"Illegal character in the set of element IDs following 'Fer' in '" + IDSet +
"'");
11305 int Pos = IDSet.Pos(
' ');
11316 CurrentID = IDSet.SubString(1, Pos - 1);
11317 IDSet = IDSet.SubString(Pos + 1, IDSet.Length() - Pos);
11329 TimetableMessage(GiveMessages,
"The element ID '" + CurrentID +
"' following 'Fer' is not an exit");
11336 if(!ExitList.empty())
11338 for(
TNumListIterator ELIT = ExitList.begin(); ELIT != ExitList.end(); ELIT++)
11340 if(*ELIT == VecPos)
11342 TimetableMessage(GiveMessages,
"The element ID '" + CurrentID +
"' following 'Fer' duplicates an earlier element");
11349 ExitList.push_back(VecPos);
11359 Pos = IDSet.Pos(
' ');
11366 int &Mass,
double &MaxBrakeRate,
double &PowerAtRail,
int &SignallerSpeed,
bool GiveMessages)
11373 AnsiString Remainder =
"";
11374 int SemiColonCount = 0;
11376 for(
int x = 1; x < TrainInfoStr.Length() + 1; x++)
11378 if(TrainInfoStr[x] ==
';')
11383 if((SemiColonCount != 6) && (SemiColonCount != 7) && (SemiColonCount != 1) && (SemiColonCount != 0))
11385 TimetableMessage(GiveMessages,
"Error in train information in '" + TrainInfoStr +
11386 "'. Should be headcode + optional description for a continuing service;" +
11387 " or headcode, description, start speed, max running speed, mass, brake force, power (and optional signaller max. speed) for a new service");
11391 if(SemiColonCount == 0)
11393 HeadCode = TrainInfoStr;
11402 if(SemiColonCount == 1)
11404 Pos = TrainInfoStr.Pos(
';');
11405 HeadCode = TrainInfoStr.SubString(1, Pos - 1);
11406 Description = TrainInfoStr.SubString(Pos + 1, TrainInfoStr.Length() - Pos);
11412 if(Description ==
"")
11414 TimetableMessage(GiveMessages,
"Train description missing in '" + TrainInfoStr +
"'");
11418 if(Description.Length() > 60)
11420 TimetableMessage(GiveMessages,
"Train description too long, limit of 60 characters '" + TrainInfoStr +
"'");
11424 for(
int x = 1; x < Description.Length() + 1; x++)
11426 if((Description[x] <
' ') || (Description[x] >
'~'))
11428 TimetableMessage(GiveMessages,
"Train description contains invalid characters in '" + TrainInfoStr +
"'");
11437 Pos = TrainInfoStr.Pos(
';');
11438 HeadCode = TrainInfoStr.SubString(1, Pos - 1);
11439 Remainder = TrainInfoStr.SubString(Pos + 1, TrainInfoStr.Length() - Pos);
11445 Pos = Remainder.Pos(
';');
11446 Description = Remainder.SubString(1, Pos - 1);
11447 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
11448 if(Description ==
"")
11450 TimetableMessage(GiveMessages,
"Train description missing in '" + TrainInfoStr +
"'");
11454 if(Description.Length() > 60)
11456 TimetableMessage(GiveMessages,
"Train description too long, limit of 60 characters '" + TrainInfoStr +
"'");
11460 for(
int x = 1; x < Description.Length() + 1; x++)
11462 if((Description[x] <
' ') || (Description[x] > 126))
11464 TimetableMessage(GiveMessages,
"Train description contains invalid characters in '" + TrainInfoStr +
"'");
11469 Pos = Remainder.Pos(
';');
11470 AnsiString StartSpeedStr = Remainder.SubString(1, Pos - 1);
11472 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
11473 if(StartSpeedStr ==
"")
11475 TimetableMessage(GiveMessages,
"Train starting speed missing in '" + TrainInfoStr +
"'");
11479 for(
int x = 1; x < StartSpeedStr.Length() + 1; x++)
11481 if((StartSpeedStr[x] <
'0') || (StartSpeedStr[x] >
'9'))
11483 TimetableMessage(GiveMessages,
"Train start speed contains invalid characters in '" + TrainInfoStr +
"'");
11488 StartSpeed = StartSpeedStr.ToInt();
11494 TimetableMessage(GiveMessages,
"Train starting speed > 400km/h in '" + TrainInfoStr +
"'. Setting it to 400km/h");
11498 Pos = Remainder.Pos(
';');
11499 AnsiString MaxRunningSpeedStr = Remainder.SubString(1, Pos - 1);
11501 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
11502 if(MaxRunningSpeedStr ==
"")
11504 TimetableMessage(GiveMessages,
"Train maximum running speed missing in '" + TrainInfoStr +
"'");
11508 for(
int x = 1; x < MaxRunningSpeedStr.Length() + 1; x++)
11510 if((MaxRunningSpeedStr[x] <
'0') || (MaxRunningSpeedStr[x] >
'9'))
11512 TimetableMessage(GiveMessages,
"Train maximum running speed contains invalid characters in '" + TrainInfoStr +
"'");
11517 MaxRunningSpeed = MaxRunningSpeedStr.ToInt();
11523 TimetableMessage(GiveMessages,
"Train maximum running speed > 400km/h in '" + TrainInfoStr +
"'. Setting it to 400km/h");
11527 if(MaxRunningSpeed < 10)
11530 MaxRunningSpeed = 10;
11533 TimetableMessage(GiveMessages,
"Train maximum running speed can't be less than 10km/h in '" + TrainInfoStr +
"', it will be set to 10km/h");
11537 Pos = Remainder.Pos(
';');
11538 AnsiString MassStr = Remainder.SubString(1, Pos - 1);
11540 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
11543 TimetableMessage(GiveMessages,
"Train mass missing in '" + TrainInfoStr +
"'");
11547 for(
int x = 1; x < MassStr.Length() + 1; x++)
11549 if((MassStr[x] <
'0') || (MassStr[x] >
'9'))
11551 TimetableMessage(GiveMessages,
"Train mass contains invalid characters in '" + TrainInfoStr +
"'");
11556 Mass = MassStr.ToInt() * 1000;
11562 TimetableMessage(GiveMessages,
"Train mass > 10,000 tonnes in '" + TrainInfoStr +
"'. Setting it to 10,000 tonnes");
11568 TimetableMessage(GiveMessages,
"Train mass zero in '" + TrainInfoStr +
"'");
11572 Pos = Remainder.Pos(
';');
11573 AnsiString MaxBrakeForceStr = Remainder.SubString(1, Pos - 1);
11575 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
11576 if(MaxBrakeForceStr ==
"")
11578 TimetableMessage(GiveMessages,
"Train braking force missing in '" + TrainInfoStr +
"'");
11582 for(
int x = 1; x < (MaxBrakeForceStr.Length() + 1); x++)
11584 if((MaxBrakeForceStr[x] !=
'.') && ((MaxBrakeForceStr[x] <
'0') || (MaxBrakeForceStr[x] >
'9')))
11586 TimetableMessage(GiveMessages,
"Train braking force contains invalid characters in '" + TrainInfoStr +
"'");
11591 double MaxBrakeForce = MaxBrakeForceStr.ToDouble() * 1000;
11594 if((MaxBrakeForce / Mass) > 1)
11596 MaxBrakeForce = Mass;
11599 TimetableMessage(GiveMessages,
"Train braking force too high in '" + TrainInfoStr +
"'. Setting it to the same as the train mass");
11603 if((MaxBrakeForce / Mass) < 0.01)
11605 MaxBrakeForce = Mass * 0.01;
11608 TimetableMessage(GiveMessages,
"Train braking force too low in '" + TrainInfoStr +
"'. Setting it to 1% of the train mass");
11613 MaxBrakeRate = MaxBrakeForce / Mass * 9.81;
11615 AnsiString GrossPowerStr =
"", SignallerSpeedStr =
"";
11617 if(SemiColonCount == 6)
11619 GrossPowerStr = Remainder;
11620 SignallerSpeedStr =
"30";
11624 Pos = Remainder.Pos(
';');
11625 GrossPowerStr = Remainder.SubString(1, Pos - 1);
11626 SignallerSpeedStr = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
11629 if(GrossPowerStr ==
"")
11631 TimetableMessage(GiveMessages,
"Train power missing in '" + TrainInfoStr +
"'");
11635 for(
int x = 1; x < GrossPowerStr.Length() + 1; x++)
11637 if((GrossPowerStr[x] <
'0') || (GrossPowerStr[x] >
'9'))
11639 TimetableMessage(GiveMessages,
"Train power contains invalid characters in '" + TrainInfoStr +
"'");
11645 double GrossPower = GrossPowerStr.ToInt() * 1000;
11652 TimetableMessage(GiveMessages,
"Train power > 100,000kW in '" + TrainInfoStr +
"'. Setting it to 100,000kW");
11656 else if(GrossPower == 0)
11661 else if((GrossPower > 0) && (GrossPower < 10000))
11664 GrossPower = 10000;
11666 PowerAtRail = GrossPower * 0.8;
11670 if(SignallerSpeedStr ==
"")
11672 TimetableMessage(GiveMessages,
"Signaller speed not set in '" + TrainInfoStr +
"', either set a value or remove the extra semicolon");
11676 for(
int x = 1; x < SignallerSpeedStr.Length() + 1; x++)
11678 if((SignallerSpeedStr[x] <
'0') || (SignallerSpeedStr[x] >
'9'))
11680 TimetableMessage(GiveMessages,
"Signaller speed contains invalid characters in '" + TrainInfoStr +
"'");
11685 SignallerSpeed = SignallerSpeedStr.ToInt();
11691 TimetableMessage(GiveMessages,
"Signaller speed > 400km/h in '" + TrainInfoStr +
"'. Setting it to 400km/h");
11695 if(SignallerSpeed < 10)
11698 SignallerSpeed = 10;
11701 TimetableMessage(GiveMessages,
"Signaller speed can't be less than 10km/h in '" + TrainInfoStr +
"', it will be set to 10km/h");
11719 if(OneEntry.Length() < 7)
11721 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - should be 'R;m;d;n'");
11725 int SemiColonCount = 0;
11727 for(
int x = 1; x < OneEntry.Length() + 1; x++)
11729 if(OneEntry[x] ==
';')
11734 if(SemiColonCount != 3)
11736 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - should be 'R;m;d;n'");
11740 if((OneEntry[1] !=
'R') || (OneEntry[2] !=
';'))
11742 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - should be 'R;m;d;n'");
11746 AnsiString Remainder = OneEntry.SubString(3, OneEntry.Length() - 2);
11751 Pos = Remainder.Pos(
';');
11752 AnsiString MinutesStr = Remainder.SubString(1, Pos - 1);
11754 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
11755 if(MinutesStr ==
"")
11757 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - minute increment segment missing");
11761 if(MinutesStr.Length() > 3)
11764 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - minute value too high, maximum value is 999");
11768 for(
int x = 1; x < MinutesStr.Length() + 1; x++)
11770 if((MinutesStr[x] <
'0') || (MinutesStr[x] >
'9'))
11772 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - non-digit character in minute increment segment");
11777 RearStartOrRepeatMins = MinutesStr.ToInt();
11778 if(RearStartOrRepeatMins == 0)
11780 TimetableMessage(GiveMessages,
"Repeat minute increment is zero in: '" + OneEntry +
"' - can't have a zero value");
11784 Pos = Remainder.Pos(
';');
11785 AnsiString DigitsStr = Remainder.SubString(1, Pos - 1);
11787 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
11788 if(DigitsStr ==
"")
11790 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - headcode increment segment missing");
11794 for(
int x = 1; x < DigitsStr.Length() + 1; x++)
11796 if((DigitsStr[x] <
'0') || (DigitsStr[x] >
'9'))
11798 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - non-digit character in headcode increment segment");
11803 if(DigitsStr.Length() > 2)
11805 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - maximum number of digits for headcode increment is 2");
11809 FrontStartOrRepeatDigits = DigitsStr.ToInt();
11823 "' - a repeating service with incrementing digits must have digits as its last two headcode characters");
11827 AnsiString NumberStr = Remainder;
11829 if(NumberStr ==
"")
11831 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - number of repeats missing");
11835 if(NumberStr.Length() > 4)
11838 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - repeat value too high, no timetabled event can exceed 95 hours & 59 minutes");
11842 for(
int x = 1; x < NumberStr.Length() + 1; x++)
11844 if((NumberStr[x] <
'0') || (NumberStr[x] >
'9'))
11847 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - non-digit character in number of repeats");
11852 NumberOfRepeats = NumberStr.ToInt();
11853 if(NumberOfRepeats == 0)
11855 TimetableMessage(GiveMessages,
"Number of repeats is zero in: '" + OneEntry +
"' - if no repeats are needed the repeat should be omitted");
12027 SecondPassMessage(GiveMessages,
"Error in timetable - there appear to be no train services in the timetable, it must contain at least one");
12046 TwoLocationFlag =
false;
12052 SecondPassMessage(GiveMessages,
"Error in timetable - the following service has no listed events, there must be at least one: " + TDEntry.
HeadCode);
12066 SecondPassMessage(GiveMessages,
"Error in timetable - service must have a start event and at least one other for: " + TDEntry.
HeadCode);
12082 "Error in timetable - a signaller control service can have no more than one item (a repeat) after the start event, see: " +
12094 "Error in timetable - a signaller control service cannot have any other than a repeat after the start event, see: " + TDEntry.
HeadCode);
12121 SecondPassMessage(GiveMessages,
"Error in timetable - finish events Fns-sh and Frh-sh not permitted immediately after an Snt entry for: " +
12132 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12137 SecondPassMessage(GiveMessages,
"Error in timetable - a start event is present that is not the first event for: " + TDEntry.
HeadCode);
12147 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12152 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat is present that is not the last item for: " + TDEntry.
HeadCode);
12162 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12173 SecondPassMessage(GiveMessages,
"Error in timetable - the last item must be either a finish event or a repeat for: " + TDEntry.
HeadCode);
12183 SecondPassMessage(GiveMessages,
"Error in timetable - the last event before the repeat must be a finish for: " + TDEntry.
HeadCode);
12195 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12202 SecondPassMessage(GiveMessages,
"Error in timetable - a finish event must be either the last or last but one for: " + TDEntry.
HeadCode);
12211 SecondPassMessage(GiveMessages,
"Error in timetable - the only event that can follow a finish event is a repeat for: " +
12231 if((AVEntry0.
Command ==
"Snt") || (AVEntry0.
Command ==
"Snt-sh"))
12233 AnsiString LocationName =
"";
12249 SecondPassMessage(GiveMessages,
"Error in timetable - stopped 'Snt' or 'Snt-sh' followed by an illegal event for: " +
12250 TDEntry.
HeadCode +
". The event isn't valid for a stationary train.");
12259 SecondPassMessage(GiveMessages,
"Error in timetable - 'Snt' or 'Snt-sh' event at stop location but start speed not zero for: " +
12268 if(AVEntry0.
Command ==
"Snt-sh")
12282 SecondPassMessage(GiveMessages,
"Error in timetable - unlocated 'Snt' not followed by 'Fer', 'pas' or an arrival for: " +
12298 SecondPassMessage(GiveMessages,
"Error in timetable - 'Sfs', 'Sns', 'Sns-sh' or 'Sns-fsh' followed by an illegal event for: " +
12299 TDEntry.
HeadCode +
". The event isn't valid for a stationary train.");
12310 bool FoundFlag =
false;
12316 for(
unsigned int y = 1; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12328 SecondPassMessage(GiveMessages,
"Error in timetable - no location departure following an 'Sfs', 'Sns', 'Sns-sh'or 'Sns-fsh' event for: " +
12341 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12350 ": an event should have had a location name associated with it but it could not be found");
12356 for(
unsigned int z = y + 1; z <
TrainDataVector.at(x).ActionVector.size(); z++)
12378 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12388 SecondPassMessage(GiveMessages,
"Error in timetable - only a repeat can follow a finish entry for: " + TDEntry.
HeadCode);
12395 if(AVEntry.
Command ==
"F-nshs")
12400 SecondPassMessage(GiveMessages,
"Error in timetable - F-nshs (shuttle link) must be the last event for: " + TDEntry.
HeadCode);
12428 SecondPassMessage(GiveMessages,
"Error in timetable - a jbo event is followed by an illegal event for: " + TDEntry.
HeadCode +
12429 ". The event isn't valid for a stationary train.");
12439 SecondPassMessage(GiveMessages,
"Error in timetable - a train split can't be the last event for: " + TDEntry.
HeadCode);
12447 SecondPassMessage(GiveMessages,
"Error in timetable - a train split is followed by an illegal event for: " + TDEntry.
HeadCode +
12448 ". The event isn't valid for a stationary train.");
12466 SecondPassMessage(GiveMessages,
"Error in timetable - a 'cdt' is followed by an illegal event for: " + TDEntry.
HeadCode +
12467 ". The event isn't valid for a stationary train.");
12477 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival and departure can't be the last event for: " + TDEntry.
HeadCode);
12485 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival and departure is followed by an illegal event for: " +
12486 TDEntry.
HeadCode +
". The event isn't valid for a moving train.");
12504 SecondPassMessage(GiveMessages,
"Error in timetable - a pass time is followed by an illegal event for: " + TDEntry.
HeadCode +
12505 ". The event isn't valid for a moving train.");
12527 bool LastEntryIsAnArrival =
false;
12534 LastEntryIsAnArrival =
false;
12535 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12542 throw Exception(
"Timetable error, TimeLoc times not as initially set for " + TDEntry.
HeadCode);
12544 if(LastEntryIsAnArrival)
12548 LastEntryIsAnArrival =
false;
12554 LastEntryIsAnArrival =
true;
12561 LastEntryIsAnArrival =
true;
12562 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12569 throw Exception(
"Timetable error, TimeLoc times not as initially set for " + TDEntry.
HeadCode);
12571 if(LastEntryIsAnArrival)
12575 LastEntryIsAnArrival =
false;
12581 LastEntryIsAnArrival =
true;
12591 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12599 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival can't be the last event for: " + TDEntry.
HeadCode);
12607 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival is followed by an illegal event for: " + TDEntry.
HeadCode +
12608 ". The event isn't valid for a stationary train.");
12619 SecondPassMessage(GiveMessages,
"Error in timetable - a timed departure can't be the last event for: " + TDEntry.
HeadCode);
12627 SecondPassMessage(GiveMessages,
"Error in timetable - a timed departure is followed by an illegal event for: " + TDEntry.
HeadCode +
12628 ". The event isn't valid for a moving train.");
12642 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12649 throw Exception(
"Timetable error, TimeLoc entry has EventTime not -1 for " + TDEntry.
HeadCode);
12653 throw Exception(
"Timetable error, TimeLoc entry has neither arrival nor departure time set for " + TDEntry.
HeadCode);
12660 throw Exception(
"Timetable error, TimeTimeLoc entry has EventTime not -1 for " + TDEntry.
HeadCode);
12664 throw Exception(
"Timetable error, TimeTimeLoc entry has either arrival or departure time not set for " + TDEntry.
HeadCode);
12673 throw Exception(
"Timetable error, Cmd or PassTime entry has EventTime not set for " + TDEntry.
HeadCode);
12677 throw Exception(
"Timetable error, Cmd or PassTime entry has either arrival or departure time set for " + TDEntry.
HeadCode);
12684 throw Exception(
"Timetable error, Repeat entry has a time set for " + TDEntry.
HeadCode);
12695 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12710 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival and departure has a later arrival than departure time for: " +
12718 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival and departure has too early an arrival time for: " +
12733 SecondPassMessage(GiveMessages,
"Error in timetable - a timed location event has a time that is too early for: " + TDEntry.
HeadCode);
12745 SecondPassMessage(GiveMessages,
"Error in timetable - a timed location event has a time that is too early for: " + TDEntry.
HeadCode);
12757 SecondPassMessage(GiveMessages,
"Error in timetable - a train event has a time that is set too early for: " + TDEntry.
HeadCode +
12758 ", may be before timetable start time");
12769 AnsiString LastLocationName =
"";
12773 bool LastEntryIsAnArrival =
false;
12778 LastEntryIsAnArrival =
false;
12779 LastLocationName =
TrainDataVector.at(x).ActionVector.at(0).LocationName;
12780 if(LastLocationName !=
"")
12782 throw Exception(
"Timetable error, moving Snt entry has LocationName set for " + TDEntry.
HeadCode);
12784 for(
unsigned int y = 1; y <
TrainDataVector.at(x).ActionVector.size();
12797 SecondPassMessage(GiveMessages,
"Error in timetable - a location event is inconsistent for: " + TDEntry.
HeadCode +
" && " +
12809 SecondPassMessage(GiveMessages,
"Error in timetable - a location event is inconsistent for: " + TDEntry.
HeadCode +
" && " +
12822 TwoLocationFlag =
true;
12827 LastEntryIsAnArrival =
false;
12831 if(LastEntryIsAnArrival && (AVEntry.
LocationName != LastLocationName))
12834 "Error in timetable - a location event for a timed departure is different from the arrival location for: " + TDEntry.
HeadCode);
12839 else if(!LastEntryIsAnArrival && (AVEntry.
LocationName == LastLocationName))
12842 "Error in timetable - a location event for a timed arrival is the same as the earlier departure location for: " + TDEntry.
HeadCode);
12848 LastEntryIsAnArrival = !LastEntryIsAnArrival;
12854 LastEntryIsAnArrival =
true;
12855 LastLocationName =
TrainDataVector.at(x).ActionVector.at(0).LocationName;
12856 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12868 SecondPassMessage(GiveMessages,
"Error in timetable - a location event is inconsistent for: " + TDEntry.
HeadCode +
" && " +
12880 SecondPassMessage(GiveMessages,
"Error in timetable - a location event is inconsistent for: " + TDEntry.
HeadCode +
" && " +
12893 TwoLocationFlag =
true;
12898 LastEntryIsAnArrival =
false;
12902 if(LastEntryIsAnArrival && (AVEntry.
LocationName != LastLocationName))
12905 "Error in timetable - a location event for a timed departure is different from the arrival location for: " + TDEntry.
HeadCode);
12913 "A location event for a timed arrival is the same as the earlier departure location for: " + TDEntry.
HeadCode +
". Please correct if this is an error.\n\nThis warning will not be shown again.");
12920 LastEntryIsAnArrival = !LastEntryIsAnArrival;
12928 AnsiString LocationNameToBeChecked =
"";
12933 unsigned int y = 0;
12947 LocationNameToBeChecked = TDEntry.
ActionVector.at(y).LocationName;
12948 for(
unsigned int z = y; z < TDEntry.
ActionVector.size(); z++)
12966 for(
unsigned int a = z; a < TDEntry.
ActionVector.size(); a++)
12975 TwoLocationFlag =
true;
12986 if(TwoLocationFlag)
12996 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13001 throw Exception(
"Error, non- 'Snt', 'Fer' or Repeat entry doesn't have a location name set for " + TDEntry.
HeadCode);
13003 AnsiString LocName =
"";
13009 throw Exception(
"Error, 'Snt' entry at a stop location doesn't have a location name set for " + TDEntry.
HeadCode);
13016 throw Exception(
"Error, 'Snt' unlocated entry has a location name set for " + TDEntry.
HeadCode);
13039 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13064 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13086 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13108 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13127 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13130 if((AVEntry.
Command ==
"Sns-sh") || (AVEntry.
Command ==
"Snt-sh"))
13145 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13150 throw Exception(
"Error - timetable ActionVector entry no. " + AnsiString(y) +
" has FormatType unset for: " + TDEntry.
HeadCode);
13154 throw Exception(
"Error - timetable ActionVector entry no. " + AnsiString(y) +
" has SequenceType unset for: " + TDEntry.
HeadCode);
13158 throw Exception(
"Error - timetable ActionVector entry no. " + AnsiString(y) +
" has LocationType unset for: " + TDEntry.
HeadCode);
13162 throw Exception(
"Error - timetable ActionVector entry no. " + AnsiString(y) +
" has ShuttleLinkType unset for: " + TDEntry.
HeadCode);
13201 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13203 AnsiString LocName =
TrainDataVector.at(x).ActionVector.at(y).LocationName;
13209 SecondPassMessage(GiveMessages,
"Error in timetable - continuation names (" + LocName +
") must not be included, see service " + HC);
13222 int IncMinutes = 0;
13232 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13238 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat time exceeds 95h 59m, see service " + HC);
13244 if((
double)
TrainDataVector.at(x).ActionVector.at(y).ArrivalTime > -1)
13249 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat entry time exceeds 95h 59m, see service " + HC);
13255 if((
double)
TrainDataVector.at(x).ActionVector.at(y).DepartureTime > -1)
13260 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat entry time exceeds 95h 59m, see service " + HC);
13273 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13299 (AVEntry.
Command ==
"Fns-sh") || (AVEntry.
Command ==
"F-nshs"));
13307 if(HeadCode.Length() > 4)
13309 HeadCode = HeadCode.SubString(HeadCode.Length() - 3, 4);
13320 int ForwardCount = 0;
13321 int ReverseCount = 0;
13323 if(MainHeadCode == SecondHeadCode)
13325 SecondPassMessage(GiveMessages,
"Error in timetable - Service " + MainHeadCode +
" has an event that references itself");
13334 if(TDEntry.
HeadCode == MainHeadCode)
13336 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13351 if(ForwardCount == 0)
13354 throw Exception(
"Error, ForwardCount == 0 in CheckForDuplicateCrossReferences after called with found values");
13356 if(ForwardCount > 2)
13359 SecondPassMessage(GiveMessages,
"Error in timetable - found more than two references to " + SecondHeadCode +
" from a train whose headcode is " +
13360 MainHeadCode +
". Check the service cross references from each service, and check whether one or other service is listed twice or more.");
13369 if(TDEntry.
HeadCode == SecondHeadCode)
13371 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13386 if(ReverseCount == 0)
13388 SecondPassMessage(GiveMessages,
"Error in timetable - cross reference missing in either " + MainHeadCode +
" or " + SecondHeadCode);
13393 if(ReverseCount > 2)
13396 SecondPassMessage(GiveMessages,
"Error in timetable - found more than two references to " + MainHeadCode +
" from a train whose headcode is " +
13397 SecondHeadCode +
". Check the service cross references from each service, and check whether one or other service is listed twice or more.");
13402 if(ForwardCount != ReverseCount)
13404 SecondPassMessage(GiveMessages,
"Error in timetable - " + MainHeadCode +
" has a different number of references to " + SecondHeadCode +
13405 " than the other way round");
13436 int ForwardCount = 0;
13437 int ReverseCount = 0;
13438 unsigned int ForwardTDVectorNumber, ReverseTDVectorNumber;
13447 if(TDEntry.
HeadCode == MainHeadCode)
13449 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13452 if(!Shuttle && (AVEntry.
Command !=
"Sns-sh") && (AVEntry.
Command !=
"Snt-sh") && (AVEntry.
Command !=
"Fns-sh") && (AVEntry.
Command !=
"Frh-sh"))
13457 ForwardEntryPtr = &AVEntry;
13459 ForwardTDVectorNumber = x;
13462 else if(Shuttle && ((AVEntry.
Command ==
"Sns-sh") || (AVEntry.
Command ==
"Snt-sh") || (AVEntry.
Command ==
"Fns-sh") ||
13463 (AVEntry.
Command ==
"Frh-sh")))
13468 ForwardEntryPtr = &AVEntry;
13470 ForwardTDVectorNumber = x;
13476 if(ForwardCount == 0)
13479 throw Exception(
"Error, ForwardCount == 0 in CheckCrossReferencesAndSetData after called with found values");
13481 if(ForwardCount > 1)
13483 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + OtherHeadCode +
" from a train whose headcode is " +
13493 if(TDEntry.
HeadCode == OtherHeadCode)
13495 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13498 if(!Shuttle && (AVEntry.
Command !=
"Sns-sh") && (AVEntry.
Command !=
"Snt-sh") && (AVEntry.
Command !=
"Fns-sh") && (AVEntry.
Command !=
"Frh-sh"))
13504 ReverseEntryPtr = &AVEntry;
13505 ReverseTDVectorNumber = x;
13508 else if(Shuttle && ((AVEntry.
Command ==
"Sns-sh") || (AVEntry.
Command ==
"Snt-sh") || (AVEntry.
Command ==
"Fns-sh") || (AVEntry.
Command ==
"Frh-sh")))
13514 ReverseEntryPtr = &AVEntry;
13515 ReverseTDVectorNumber = x;
13522 if(ReverseCount == 0)
13524 SecondPassMessage(GiveMessages,
"Error in timetable - cross reference missing in either " + MainHeadCode +
" or " + OtherHeadCode);
13529 if(ReverseCount > 1)
13531 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + MainHeadCode +
" from a train whose headcode is " +
13538 bool ForwardShuttleStart = ((ForwardEntryPtr->Command ==
"Sns-sh") || (ForwardEntryPtr->Command ==
"Snt-sh"));
13539 bool ForwardShuttleFinish = ((ForwardEntryPtr->Command ==
"Fns-sh") || (ForwardEntryPtr->Command ==
"Frh-sh"));
13540 bool ReverseShuttleStart = ((ReverseEntryPtr->
Command ==
"Sns-sh") || (ReverseEntryPtr->
Command ==
"Snt-sh"));
13541 bool ReverseShuttleFinish = ((ReverseEntryPtr->
Command ==
"Fns-sh") || (ReverseEntryPtr->
Command ==
"Frh-sh"));
13545 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle train " + MainHeadCode +
" does not have a repeat");
13552 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle train " + OtherHeadCode +
" does not have a repeat");
13557 if(ForwardEntryPtr->LocationName ==
"")
13559 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + OtherHeadCode +
13560 ". One or other service does not have a location set");
13567 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + OtherHeadCode +
13568 ". One or other service does not have a location set");
13573 if(ForwardEntryPtr->LocationName != ReverseEntryPtr->
LocationName)
13575 SecondPassMessage(GiveMessages,
"Error in timetable - cross referenced train " + OtherHeadCode +
13576 " is at a different location to the referencing train " + MainHeadCode);
13584 if(ForwardEntryPtr->EventTime != ReverseEntryPtr->
EventTime)
13586 SecondPassMessage(GiveMessages,
"Error in timetable - cross referenced train " + OtherHeadCode +
13587 " has a different event time to the referencing train " + MainHeadCode);
13595 if(ForwardShuttleStart && ReverseShuttleFinish)
13600 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle service " + MainHeadCode +
13601 " first repeat restart time not consistent with finish service " + OtherHeadCode);
13607 if((ReverseEntryPtr->
Command ==
"Sfs") || (ReverseEntryPtr->
Command ==
"Sns"))
13610 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
13612 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Sfs' or 'Sns' event (" + OtherHeadCode +
13613 ") appears in the same sequence as the corresponding linked event " + MainHeadCode);
13619 if(ReverseEntryPtr->
Command ==
"Fjo")
13622 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
13624 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Fjo' event (" + OtherHeadCode +
13625 ") appears in the same sequence as the corresponding linked event " + MainHeadCode);
13631 if(ReverseEntryPtr->
Command ==
"Fns")
13634 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
13636 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Fns' event (" + OtherHeadCode +
13637 ") appears in the same sequence as the corresponding linked event " + MainHeadCode);
13643 if(ForwardEntryPtr->Command ==
"Sfs")
13645 if((ReverseEntryPtr->
Command !=
"fsp") && (ReverseEntryPtr->
Command !=
"rsp"))
13648 "Error in timetable - unable to find a corresponding split train event for the train that starts from a split whose headcode is " +
13655 if((ForwardEntryPtr->Command ==
"fsp") || (ForwardEntryPtr->Command ==
"rsp"))
13657 if(ReverseEntryPtr->
Command !=
"Sfs")
13659 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Sfs' event for the train split whose headcode is " +
13669 SecondPassMessage(GiveMessages,
"Error in timetable - can't find timetabled location '" + ForwardEntryPtr->LocationName +
"' in railway - perhaps there are concourses without platforms?");
13676 SecondPassMessage(GiveMessages,
"Error in timetable - can't find any named location elements at '" + ForwardEntryPtr->LocationName +
"' - perhaps there are concourses without platforms?");
13683 SecondPassMessage(GiveMessages,
"Error in timetable - location too short to split a train at " + ForwardEntryPtr->LocationName);
13688 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
13699 if(ForwardEntryPtr->Command ==
"Sns")
13701 if(ReverseEntryPtr->
Command !=
"Fns")
13703 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Fns' event for the 'Sns' train whose headcode is " +
13704 MainHeadCode +
" and is formed from a service with headcode " + OtherHeadCode);
13710 if(ForwardEntryPtr->Command ==
"Fns")
13712 if(ReverseEntryPtr->
Command !=
"Sns")
13714 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Sns' event for the train whose headcode is " + MainHeadCode +
13715 " and forms a new service with headcode " + OtherHeadCode);
13722 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
13733 if(ForwardEntryPtr->Command ==
"jbo")
13735 if(ReverseEntryPtr->
Command !=
"Fjo")
13737 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Fjo' event for the train whose headcode is " + MainHeadCode +
13738 " and is joined by a train with headcode " + OtherHeadCode);
13744 if(ForwardEntryPtr->Command ==
"Fjo")
13746 if(ReverseEntryPtr->
Command !=
"jbo")
13748 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'jbo' event for the train whose headcode is " + MainHeadCode +
13749 " and joins a train with headcode " + OtherHeadCode);
13756 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
13766 if(ForwardShuttleStart)
13769 if(!ReverseShuttleFinish)
13772 SecondPassMessage(GiveMessages,
"Error in timetable - incorrect shuttle link to train whose headcode is " + MainHeadCode +
13773 " from train whose headcode is " + OtherHeadCode +
", has to be Fns-sh, Frh-sh");
13779 if(ReverseShuttleStart)
13782 if(!ForwardShuttleFinish)
13785 SecondPassMessage(GiveMessages,
"Error in timetable - incorrect shuttle link to train whose headcode is " + OtherHeadCode +
13786 " from train whose headcode is " + MainHeadCode +
", has to be Fns-sh, Frh-sh");
13793 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
13805 bool MainRepeat =
false, OtherRepeat =
false;
13815 OtherRepeat =
true;
13818 if((MainRepeat && !OtherRepeat) || (!MainRepeat && OtherRepeat))
13820 SecondPassMessage(GiveMessages,
"Error in timetable - only one repeat is provided for the train whose headcode is " + MainHeadCode +
13821 " and the associated train with headcode " + OtherHeadCode);
13826 if(MainRepeat && OtherRepeat)
13832 SecondPassMessage(GiveMessages,
"Error in timetable - repeat items don't correspond for the train whose headcode is " + MainHeadCode +
13833 " and the associated train with headcode " + OtherHeadCode);
13855 while(Input[1] ==
' ')
13857 if(Input.Length() > 1)
13859 Input = Input.SubString(2, Input.Length() - 1);
13873 while(Input[Input.Length()] ==
' ')
13875 if(Input.Length() > 1)
13877 Input = Input.SubString(1, Input.Length() - 1);
13887 AnsiString Output =
"";
13888 bool DelimiterFound =
false;
13890 for(
int x = 1; x < Input.Length() + 1; x++)
13894 if(Input[x] ==
' ')
13899 if((Input[x] !=
',') && (Input[x] !=
';'))
13901 DelimiterFound =
false;
13902 Output = Output + Input[x];
13906 DelimiterFound =
true;
13907 Output = Output + Input[x];
13919 DelimiterFound =
false;
13920 for(
int x = Input.Length(); x > 0; x--)
13924 if(Input[x] ==
' ')
13929 if((Input[x] !=
',') && (Input[x] !=
';'))
13931 DelimiterFound =
false;
13932 Output = AnsiString(Input[x]) + Output;
13936 DelimiterFound =
true;
13937 Output = AnsiString(Input[x]) + Output;
13962 if((AVEntry0.
Command !=
"Snt") && (AVEntry0.
Command !=
"Snt-sh"))
13964 throw Exception(
"Error, first entry not 'Snt' or 'Snt-sh' in IsSNTEntryLocated");
13976 LocationName = LocRear;
13980 LocationName = LocFront;
13982 if(LocationName ==
"")
14003 for(
unsigned int y = 0; y < TDEntry.
ActionVector.size(); y++)
14044 int RearPosition = 0, FrontPosition = 0, RearExitPos = 0;
14047 if(RearPosition < 0)
14054 if(FrontPosition < 0)
14065 for(
int x = 0; x < 4; x++)
14067 if(RearTrackElement.
Conn[x] == FrontPosition)
14082 TimetableMessage(GiveMessages,
"Front of train attempting to start on a continuation at: " + FrontElementStr);
14089 TimetableMessage(GiveMessages,
"Train attempting to start on a level crossing at: " + FrontElementStr);
14095 TimetableMessage(GiveMessages,
"Train attempting to start on a level crossing at: " + RearElementStr);
14100 if((RearType ==
Points) && (RearExitPos == 3))
14102 TimetableMessage(GiveMessages,
"Front of train attempting to start on element connected to diverging points at: " + RearElementStr);
14108 TimetableMessage(GiveMessages,
"Rear of train attempting to start on element connected to diverging points at: " + FrontElementStr);
14123 AnsiString(RearExitPos));
14134 int FrontPosition = RearTrackElement.
Conn[RearExitPos];
14136 int FrontEntryPos = RearTrackElement.
ConnLinkPos[RearExitPos];
14139 AnsiString RearName, FrontName;
14155 FrontName = FrontTrackElement.
ElementID;
14158 int LockedVectorNumber;
14328 "," + AnsiString(IncDigits));
14331 throw Exception(
"Error, last 2 characters not both digits and IncDigits > 0 in GetRepeatHeadCode");
14336 return(BaseHeadCode);
14338 int BaseDigits = BaseHeadCode.SubString(3, 2).ToInt();
14339 int NextRepeatDigits = BaseDigits + (IncDigits * RepeatNumber);
14341 while(NextRepeatDigits >= 100)
14343 NextRepeatDigits -= 100;
14345 AnsiString NextRepeatDigitsStr = AnsiString(NextRepeatDigits);
14347 if(NextRepeatDigitsStr.Length() < 2)
14349 NextRepeatDigitsStr = AnsiString(
'0') + NextRepeatDigitsStr;
14351 AnsiString NextRepeatHeadCode = BaseHeadCode.SubString(1, 2) + NextRepeatDigitsStr;
14354 return(NextRepeatHeadCode);
14362 AnsiString(RepeatNumber) +
"," + AnsiString(IncMinutes));
14363 TDateTime NextRepeatTime = BasicTime + TDateTime(((
double)(RepeatNumber * IncMinutes)) / 1440.0);
14365 return(NextRepeatTime);
14374 AnsiString(
double(ReverseEventTime)) +
"," + AnsiString(RepeatMinutes));
14375 int ForwardSecs = int(
double(ForwardEventTime) * 86400);
14376 int ReverseSecs = int(
double(ReverseEventTime) * 86400);
14377 int RepeatSecs = RepeatMinutes * 60;
14379 if((ForwardSecs > (ReverseSecs - RepeatSecs + 10)) || (ForwardSecs < (ReverseSecs - RepeatSecs - 10)))
14414 NonRepeatingHeadCode);
14415 int ForwardCount = 0;
14416 int ReverseCount = 0;
14417 unsigned int ForwardTDVectorNumber, ReverseTDVectorNumber;
14427 if(TDEntry.
HeadCode == MainHeadCode)
14429 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14435 ForwardEntryPtr = &AVEntry;
14437 ForwardTDVectorNumber = x;
14442 if(ForwardCount == 0)
14445 throw Exception(
"Error, ForwardCount == 0 in CheckNonRepeatingShuttleLinksAndSetData after called with found values");
14447 if(ForwardCount > 1)
14449 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + NonRepeatingHeadCode +
" from a train whose headcode is " +
14459 if(TDEntry.
HeadCode == NonRepeatingHeadCode)
14461 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14468 ReverseEntryPtr = &AVEntry;
14469 ReverseTDVectorNumber = x;
14475 if(ReverseCount == 0)
14477 SecondPassMessage(GiveMessages,
"Error in timetable - cross reference missing in either " + MainHeadCode +
" or " + NonRepeatingHeadCode);
14482 if(ReverseCount > 1)
14484 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + MainHeadCode +
" from a train whose headcode is " +
14485 NonRepeatingHeadCode);
14490 if(((ForwardEntryPtr->Command ==
"F-nshs") || (ForwardEntryPtr->Command ==
"Sns-fsh")) && (MainTrainDataPtr->
ActionVector.back().FormatType ==
Repeat))
14492 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle connecting train " + MainHeadCode +
" shouldn't have a repeat");
14497 if((ForwardEntryPtr->Command !=
"F-nshs") && (ForwardEntryPtr->Command !=
"Sns-fsh") && (MainTrainDataPtr->
ActionVector.back().FormatType !=
Repeat))
14499 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle train " + MainHeadCode +
" does not have a repeat item");
14504 if(ForwardEntryPtr->LocationName ==
"")
14506 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + NonRepeatingHeadCode +
14507 ". One or other service does not have a location set");
14514 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + NonRepeatingHeadCode +
14515 ". One or other service does not have a location set");
14520 if(ForwardEntryPtr->LocationName != ReverseEntryPtr->
LocationName)
14522 SecondPassMessage(GiveMessages,
"Error in timetable - cross referenced train " + NonRepeatingHeadCode +
14523 " is at a different location to the referencing train " + MainHeadCode);
14528 if(ForwardEntryPtr->Command ==
"F-nshs")
14531 if(ForwardEntryPtr->EventTime != ReverseEntryPtr->
EventTime)
14533 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle in-link service " + MainHeadCode +
14534 " finish time not consistent with start time of shuttle service " + NonRepeatingHeadCode);
14540 if(ForwardEntryPtr->Command ==
"Fns-sh")
14544 MainTrainDataPtr->
ActionVector.back().RearStartOrRepeatMins, MainTrainDataPtr->
ActionVector.back().NumberOfRepeats))
14546 SecondPassMessage(GiveMessages,
"Error in timetable - service " + NonRepeatingHeadCode +
", which links out from shuttle service " + MainHeadCode +
14547 ", has the wrong start time. It should correspond to the finish time of the last shuttle.");
14553 if((ForwardEntryPtr->Command ==
"F-nshs") || (ForwardEntryPtr->Command ==
"Sns-fsh"))
14556 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
14558 SecondPassMessage(GiveMessages,
"Error in timetable - the non repeating link service " + NonRepeatingHeadCode +
14559 " appears in the same sequence as the corresponding shuttle service " + MainHeadCode);
14577 if(ForwardEntryPtr->Command ==
"Sns-sh")
14579 if(ReverseEntryPtr->
Command !=
"F-nshs")
14581 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'F-nshs' event for the 'Sns-sh' train whose headcode is " +
14582 MainHeadCode +
" and is a new shuttle service formed from the service with headcode " + NonRepeatingHeadCode);
14588 if(ForwardEntryPtr->Command ==
"F-nshs")
14590 if(ReverseEntryPtr->
Command !=
"Sns-sh")
14592 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Sns-sh' event for the 'F-nshs' train whose headcode is " +
14593 MainHeadCode +
" and forms a new shuttle service with headcode " + NonRepeatingHeadCode);
14600 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
14611 if(ForwardEntryPtr->Command ==
"Sns-fsh")
14613 if(ReverseEntryPtr->
Command !=
"Fns-sh")
14616 "Error in timetable - unable to find a corresponding 'Fns-sh' event for the 'Sns-fsh' non-shuttle service whose headcode is " + MainHeadCode +
14617 " formed from a shuttle service with headcode " + NonRepeatingHeadCode);
14623 if(ForwardEntryPtr->Command ==
"Fns-sh")
14625 if(ReverseEntryPtr->
Command !=
"Sns-fsh")
14628 "Error in timetable - unable to find a corresponding 'Sns-fsh' event for the 'Fns-sh' shuttle service whose headcode is " + MainHeadCode +
14629 " and forms a new non-shuttle service with headcode " + NonRepeatingHeadCode);
14636 ForwardEntryPtr->NonRepeatingShuttleLinkEntryPtr = OtherTrainDataPtr;
14660 +
"," + AnsiString(
double(ReverseEventTime)) +
"," + AnsiString(RepeatMinutes) +
"," + AnsiString(RepeatNumber));
14661 int ForwardSecs = int(
double(ForwardEventTime) * 86400);
14662 int ReverseSecs = int(
double(ReverseEventTime) * 86400);
14663 int RepeatSecs = RepeatMinutes * RepeatNumber * 60;
14665 if((ReverseSecs > (ForwardSecs + RepeatSecs + 10)) || (ReverseSecs < (ForwardSecs + RepeatSecs - 10)))
14689 throw Exception(
"Error - last entry in " + TDEntryPtr->
HeadCode +
" service is not a repeat - should have already found this error");
14692 AnsiString OriginalHeadCode = TDEntryPtr->
HeadCode;
14693 AnsiString LastActionCommand = (TDEntryPtr->
ActionVector.end() - 2)->Command;
14695 if((LastActionCommand !=
"Fns") && (LastActionCommand !=
"Fns-sh") && (LastActionCommand !=
"Frh-sh"))
14697 SecondPassMessage(GiveMessages,
"Error in timetable - last event in shuttle service " + TDEntryPtr->
HeadCode +
" is not 'Fns', 'Fns-sh' or 'Frh-sh'");
14702 while(LastActionCommand ==
"Fns")
14704 TDEntryPtr = (TDEntryPtr->
ActionVector.end() - 2)->LinkedTrainEntryPtr;
14705 LastActionCommand = (TDEntryPtr->
ActionVector.end() - 2)->Command;
14706 if((LastActionCommand !=
"Fns") && (LastActionCommand !=
"Fns-sh") && (LastActionCommand !=
"Frh-sh"))
14709 "Error in timetable - last event in a continuation shuttle service (i.e links back to a shuttle) whose headcode is " + TDEntryPtr->
HeadCode +
14710 " is not 'Fns', 'Fns-sh' or 'Frh-sh'");
14717 if((TDEntryPtr->
ActionVector.end() - 2)->LinkedTrainEntryPtr != ShuttleStartAddress)
14720 " is a shuttle finish, but it doesn't link back to the start of the original shuttle starting service " + OriginalHeadCode +
14721 ". The linking of two or more shuttles is not permitted.");
14741 ShowMessage(Message);
14759 ShowMessage(Message);
14798 AnsiString(ActionEventType) +
"," + LocationID);
14799 AnsiString BaseLog =
"", Prefix =
"", ErrorLog =
"", WarningStr =
"";
14804 Prefix =
" ERROR: ";
14807 Prefix =
" HELD: ";
14808 ErrorLog =
" can't enter railway, train obstructing entry position ";
14809 WarningStr =
" can't enter railway, train obstructing entry position ";
14814 Prefix =
" HELD: ";
14815 ErrorLog =
" can't enter railway, route set against it at entry position ";
14816 WarningStr =
" can't enter railway, route set against it at entry position ";
14821 Prefix =
" HELD: ";
14822 ErrorLog =
" can't be created, train obstructing ";
14823 WarningStr =
" can't be created, train obstructing ";
14828 Prefix =
" HELD: ";
14829 ErrorLog =
" can't be created on a locked route at ";
14830 WarningStr =
" can't be created on a locked route at ";
14835 Prefix =
" HELD: ";
14836 ErrorLog =
" can't enter on a locked route at ";
14837 WarningStr =
" can't enter on a locked route at ";
14842 Prefix =
" HELD: ";
14843 ErrorLog =
" can't be created, diverging points at ";
14844 WarningStr =
" can't be created, diverging points at ";
14849 ErrorLog =
" left railway unexpectedly at ";
14854 ErrorLog =
" left railway at an incorrect exit at ";
14859 ErrorLog =
" failed to split - location too short at ";
14860 WarningStr =
" failed to split, location too short at ";
14865 Prefix =
" HELD: ";
14866 ErrorLog =
" unable to split - other train obstructing at ";
14867 WarningStr =
" unable to split - other train obstructing at ";
14872 ErrorLog =
" stopped at buffers unexpectedly at position ";
14876 ErrorLog =
" failed to stop at ";
14881 ErrorLog =
" failed to split at ";
14886 ErrorLog =
" failed to be joined by other train at ";
14891 ErrorLog =
" failed to join other train at ";
14896 ErrorLog =
" failed to terminate at ";
14901 ErrorLog =
" failed to form new service at ";
14906 ErrorLog =
" failed to exit railway ";
14911 ErrorLog =
" failed to change direction at ";
14916 ErrorLog =
" failed to pass ";
14921 ErrorLog =
" facing buffers and unable to start at ";
14925 ErrorLog =
" DERAILED at position ";
14926 Prefix =
" DERAILMENT: ";
14931 ErrorLog =
" CRASHED INTO BUFFERS at ";
14932 Prefix =
" CRASH: ";
14937 ErrorLog =
" CRASHED INTO ROAD TRAFFIC AT A LEVEL CROSSING at ";
14938 Prefix =
" CRASH: ";
14943 ErrorLog =
" CRASHED INTO " + OtherHeadCode +
" at position ";
14944 Prefix =
" CRASH: ";
14948 else if(ActionEventType ==
FailSPAD)
14950 ErrorLog =
" PASSED SIGNAL AT DANGER at position ";
14951 Prefix =
" SPAD: ";
14956 ErrorLog =
"Signals reset ahead of train, route cancelled at position ";
14957 Prefix =
" SPAD RISK: ";
14962 ErrorLog =
" forced a route cancellation by occupying it incorrectly at ";
14966 Prefix =
" WARNING: ";
14967 ErrorLog =
" waiting to join " + OtherHeadCode +
" at ";
14968 WarningStr =
" waiting to join " + OtherHeadCode +
" at ";
14973 Prefix =
" WARNING: ";
14974 ErrorLog =
" waiting to be joined by " + OtherHeadCode +
" at ";
14975 WarningStr =
" waiting to be joined by " + OtherHeadCode +
" at ";
15013 std::ofstream OutFile(
"TrainData.csv");
15017 ShowMessage(
"Output file TrainData.csv failed to open");
15024 OutFile <<
"HeadCode" <<
',' <<
"Description" <<
',' <<
"StartSpeed" <<
',' <<
"MaxRunningSpeed" <<
',' <<
"NumberOfTrains" <<
'\n' <<
'\n';
15029 OutFile <<
',' <<
"FormatType" <<
',' <<
"EventTime" <<
',' <<
"ArrivalTime" <<
',' <<
"DepartureTime" <<
',' <<
"LocationName" <<
',' <<
"Command" <<
15030 ',' <<
"OtherHeadCode" <<
',' <<
"LinkedTrainEntryPtr" <<
',' <<
"RearStartOrRepeatMins" <<
',' <<
"FrontStartOrRepeatDigits" <<
',' <<
15031 "RepeatNumber" <<
'\n' <<
'\n';
15032 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15035 AnsiString TimetableEntryTypeStr;
15041 TimetableEntryTypeStr =
"NoFormat";
15047 TimetableEntryTypeStr =
"TimeLoc";
15053 TimetableEntryTypeStr =
"TimeTimeLoc";
15059 TimetableEntryTypeStr =
"TimeCmd";
15065 TimetableEntryTypeStr =
"StartNew";
15071 TimetableEntryTypeStr =
"TimeCmdHeadCode";
15077 TimetableEntryTypeStr =
"FinRemHere";
15083 TimetableEntryTypeStr =
"FNSShuttle";
15089 TimetableEntryTypeStr =
"SNTShuttle";
15095 TimetableEntryTypeStr =
"SNSShuttle";
15101 TimetableEntryTypeStr =
"SNSNonRepeatFromShuttle";
15107 TimetableEntryTypeStr =
"FSHNewService";
15113 TimetableEntryTypeStr =
"Repeat";
15119 TimetableEntryTypeStr =
"Default";
15130 OutFile <<
',' <<
',' <<
"Mass" <<
',' <<
"MaxBrakeRate" <<
',' <<
"PowerAtRail" <<
',' <<
"TrainID" <<
',' <<
"RunningEntry" <<
'\n' <<
'\n';
15131 for(
unsigned int y = 0; y <
TrainDataVector.at(x).TrainOperatingDataVector.size(); y++)
15134 AnsiString RunningEntryStr;
15140 RunningEntryStr =
"NotStarted";
15146 RunningEntryStr =
"Running";
15152 RunningEntryStr =
"Exited";
15156 OutFile <<
',' <<
',' << TOD.
TrainID <<
',' << RunningEntryStr.c_str() <<
',' <<
'\n';
15173 ShowMessage(Message);
15174 BaseTime = TDateTime::CurrentDateTime();
15188 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
15201 TTrain *NewTrain =
new TTrain(1, 0, 0,
"", 0, 1, 0, 0, 0, (
TTrainMode)0, 0, 0, 0, 0, 0);
15203 for(
int x = 0; x < NumberOfTrains; x++)
15205 *NewTrain =
TTrain(2, 0, 0,
"", 0, 1, 0, 0, 0, (
TTrainMode)0, 0, 0, 0, 0, 0);
15225 int NumberOfTrains;
15232 for(
int x = 0; x < NumberOfTrains; x++)
15269 for(
int x = 0; x < LockedRouteVectorSize; x++)
15276 LockedRouteObject.
LockStartTime = TDateTime(LockStartTimeDouble);
15287 int LockedRouteVectorSize;
15294 for(
int x = 0; x < LockedRouteVectorSize; x++)
15352 for(
int x = 0; x < ContinuationAutoSigVectorSize; x++)
15360 ContinuationAutoSigObject.
PassoutTime = TDateTime(PassoutTimeDouble);
15371 int ContinuationAutoSigVectorSize;
15378 for(
int x = 0; x < ContinuationAutoSigVectorSize; x++)
15448 if(AVFirstEntry.
Command ==
"Snt")
15472 CTEMMP.second = CTEEntry;
15479 throw Exception(
"Error, Last ActionVectorEntry not a repeat in BuildContinuationTrainExpectationMultiMap");
15487 CTEMMP.second = CTEEntry;
15508 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
15525 if((VecPos < 0) || (VecPos >= (
int)
TrainVector.size()))
15527 throw Exception(
"Out of Range Error, vector size: " + AnsiString(
TrainVector.size()) +
", VecPos: " + AnsiString(VecPos) +
" in TrainVectorAt");
15538 AnsiString RetStr =
"", PartStr =
"";
15653 AnsiString TTFileName = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
15657 TTFileName = CurDir +
"\\Formatted timetables\\Timetable " + TTFileName +
"; " + RailwayTitle +
"; " + TimetableTitle +
".csv";
15659 AnsiString ShortTTName =
"";
15661 for(
int x = TTFileName.Length(); x > 0; x--)
15663 if(TTFileName[x] ==
'\\')
15665 ShortTTName = TTFileName.SubString(x + 1, TTFileName.Length() - x - 4);
15670 ShowMessage(
"Creates two timetables named " + ShortTTName +
15671 " in the 'Formatted timetables' folder, one in service order in '.csv' format, and one in chronological order in '.txt' format");
15673 Screen->Cursor = TCursor(-11);
15675 AnsiString FormatNoDPStr =
"#######0";
15676 AnsiString TableTitle =
"", TimetableTimeStr =
"", MassStr =
"", PowerStr =
"", BrakeStr =
"", MaxSpeedStr =
"", FirstHeadCode =
"", Header =
"";
15679 TableTitle =
"Railway: " + RailwayTitle +
"; Timetable: " + TimetableTitle +
"; Start time: " + TimetableTimeStr;
15686 MassStr =
"", PowerStr =
"", BrakeStr =
"", MaxSpeedStr =
"";
15688 if(TrainDataEntry.
Mass > 0)
15690 MassStr =
"; Mass " + AnsiString::FormatFloat(FormatNoDPStr, ((
double)TrainDataEntry.
Mass) / 1000) +
"Te; ";
15694 PowerStr =
"Power " + AnsiString::FormatFloat(FormatNoDPStr, TrainDataEntry.
PowerAtRail / 1000 / 0.8) +
"kW; ";
15698 BrakeStr =
"Brake force " + AnsiString::FormatFloat(FormatNoDPStr, (TrainDataEntry.
MaxBrakeRate * TrainDataEntry.
Mass / 9810)) +
"Te; ";
15702 MaxSpeedStr =
"Maximum speed " + AnsiString::FormatFloat(FormatNoDPStr, TrainDataEntry.
MaxRunningSpeed) +
" km/h";
15704 FirstHeadCode = TrainDataEntry.
HeadCode;
15705 int IncDigits = 0, IncMinutes = 0;
15707 if(!ActionVector.empty())
15709 if(ActionVector.at(ActionVector.size() - 1).FormatType ==
Repeat)
15711 IncDigits = ActionVector.at(ActionVector.size() - 1).FrontStartOrRepeatDigits;
15712 IncMinutes = ActionVector.at(ActionVector.size() - 1).RearStartOrRepeatMins;
15720 if((TrainDataEntry.
Description !=
"") && (MassStr !=
""))
15722 OneTTLine.
Header = TrainDataEntry.
Description + MassStr + PowerStr + BrakeStr + MaxSpeedStr;
15730 for(
unsigned int z = 0; z < ActionVector.size(); z++)
15735 AnsiString PartStr =
"", TimeStr =
"";
15752 PartStr =
"Enters at " + ActionVectorEntry.
LocationName;
15756 PartStr =
"Created at " + ActionVectorEntry.
LocationName;
15766 PartStr =
"Enters at " + LocName;
15779 PartStr =
"Created at " + LocName;
15793 PartStr =
"Enters at " + ActionVectorEntry.
LocationName;
15798 PartStr =
"Repeat shuttle service at " + ActionVectorEntry.
LocationName +
" from ";
15804 else if(ActionVectorEntry.
Command ==
"Sfs")
15806 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" split from";
15810 else if(ActionVectorEntry.
Command ==
"Sns")
15812 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" from";
15820 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" from";
15826 PartStr =
"Repeat shuttle service at " + ActionVectorEntry.
LocationName +
" from ";
15834 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" from";
15837 AnsiString FirstHeadCode = TDE->
HeadCode;
15841 TimeStr =
GetRepeatHeadCode(36, FirstHeadCode, LastRepeatNumber, IncrementalDigits) +
" at " +
15853 PartStr =
"Arrives at " + ActionVectorEntry.
LocationName;
15855 OneTTEntry.
Action = PartStr;
15856 OneTTEntry.
Time = TimeStr;
15858 PartStr =
"Departs from " + ActionVectorEntry.
LocationName;
15863 PartStr =
"Arrives & departs " + ActionVectorEntry.
LocationName;
15869 PartStr =
"Arrives at " + ActionVectorEntry.
LocationName;
15874 PartStr =
"Departs from " + ActionVectorEntry.
LocationName;
15882 else if(ActionVectorEntry.
Command ==
"jbo")
15884 PartStr =
"Joined at " + ActionVectorEntry.
LocationName +
" by";
15888 else if(ActionVectorEntry.
Command ==
"fsp")
15890 PartStr =
"Splits from front at " + ActionVectorEntry.
LocationName +
" to form";
15894 else if(ActionVectorEntry.
Command ==
"rsp")
15896 PartStr =
"Splits from rear at " + ActionVectorEntry.
LocationName +
" to form";
15900 else if(ActionVectorEntry.
Command ==
"cdt")
15902 PartStr =
"Changes direction at " + ActionVectorEntry.
LocationName;
15908 if(ActionVectorEntry.
Command ==
"Fns")
15910 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
15914 else if(ActionVectorEntry.
Command ==
"F-nshs")
15916 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
15922 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service ";
15929 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
15935 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
15942 PartStr =
"Terminates shuttle service at " + ActionVectorEntry.
LocationName;
15947 else if(ActionVectorEntry.
Command ==
"Frh")
15949 PartStr =
"Terminates at " + ActionVectorEntry.
LocationName;
15954 if(ActionVector.at(z - 1).EventTime != TDateTime(-1))
15958 else if(ActionVector.at(z - 1).ArrivalTime != TDateTime(-1))
15968 else if(ActionVectorEntry.
Command ==
"Fer")
15970 AnsiString AllowedExits;
15974 else if(ActionVectorEntry.
Command ==
"Fjo")
15976 PartStr =
"At " + ActionVectorEntry.
LocationName +
" joins";
15985 OneTTEntry.
Action = PartStr;
15986 OneTTEntry.
Time = TimeStr;
15993 AllTTTrains->push_back(OneTTLine);
15997 std::ofstream TTFile(TTFileName.c_str());
16001 StopTTClockMessage(64,
"Formatted timetable file failed to open - can't be created");
16002 delete AllTTTrains;
16037 TTFile << TableTitle.c_str() <<
'\n' <<
'\n';
16038 for(
unsigned int x = 0; x < AllTTTrains->size(); x++)
16040 TTFile << AllTTTrains->at(x).Header.c_str();
16043 for(
int y = 0; y < AllTTTrains->at(x).NumberOfTrains; y++)
16045 if(y < (AllTTTrains->at(x).NumberOfTrains - 1))
16047 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).HeadCode.c_str() <<
',';
16051 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).HeadCode.c_str();
16054 TTFile <<
'\n' <<
'\n';
16056 for(
unsigned int z = 0; z < AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(0).OneFormattedTrainVector.size(); z++)
16058 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(0).OneFormattedTrainVector.at(z).Action.c_str() <<
',';
16059 for(
int y = 0; y < AllTTTrains->at(x).NumberOfTrains; y++)
16061 if(y < (AllTTTrains->at(x).NumberOfTrains - 1))
16063 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Time.c_str() <<
',';
16067 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Time.c_str();
16072 TTFile <<
'\n' <<
'\n';
16077 AnsiString TTFileName2 = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
16079 TTFileName2 = CurDir +
"\\Formatted timetables\\Timetable " + TTFileName2 +
"; " + RailwayTitle +
"; " + TimetableTitle +
".txt";
16081 std::ofstream TTFile2(TTFileName2.c_str());
16085 StopTTClockMessage(67,
"Chronological timetable file failed to open - can't be created");
16086 delete AllTTTrains;
16090 typedef std::multimap<AnsiString, AnsiString>TAnsiMultiMap;
16091 std::multimap<AnsiString, AnsiString>::iterator AMMIT;
16092 std::pair<AnsiString, AnsiString>AnsiMultiMapEntry;
16094 TAnsiMultiMap *TAMM =
new TAnsiMultiMap;
16099 TTFile2 << TableTitle.c_str() <<
'\n' <<
'\n';
16100 for(
unsigned int x = 0; x < AllTTTrains->size(); x++)
16102 for(
int y = 0; y < AllTTTrains->at(x).NumberOfTrains; y++)
16104 for(
unsigned int z = 0; z < AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.size(); z++)
16106 bool GiveMessagesFalse =
false;
16107 AnsiString TimeString = AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Time;
16108 AnsiString HeadCodeString = AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).HeadCode;
16109 AnsiString ActionString = AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Action;
16114 AnsiString OtherHeadCode = TimeString.SubString(1, 4);
16115 TimeString = TimeString.SubString(9, 5);
16116 ActionString +=
" " + OtherHeadCode;
16118 if(TimeString.SubString(1, 7) ==
"End at ")
16121 TimeString = TimeString.SubString(8, 5);
16123 AnsiString OneLine = TimeString +
' ' + HeadCodeString +
' ' + ActionString +
'\n';
16124 AnsiMultiMapEntry.first = TimeString;
16125 AnsiMultiMapEntry.second = OneLine;
16126 TAMM->insert(AnsiMultiMapEntry);
16131 for(AMMIT = TAMM->begin(); AMMIT != TAMM->end(); AMMIT++)
16133 TTFile2 << (AMMIT->second).c_str();
16135 delete AllTTTrains;
16144 bool AtLocChecked,
bool DirChecked,
int ArrRange,
int DepRange)
16148 bool AnalysisError =
false;
16149 AnsiString SequenceLog =
"SequenceLog\n";
16191 TTrainDataVector::iterator TDVIt, TDVCopyIt;
16193 int IteratorNumber = 0;
16194 AnsiString AnsiSuffix =
"";
16199 for(TDVCopyIt = TrainDataVectorCopy.begin() + IteratorNumber; TDVCopyIt != TrainDataVectorCopy.end(); TDVCopyIt++)
16201 if(TDVCopyIt->ServiceReference == TDVIt->ServiceReference)
16204 AnsiSuffix = AnsiString(Suffix);
16205 TDVCopyIt->ServiceReference = TDVIt->ServiceReference +
"/" + AnsiSuffix;
16209 SequenceLog +=
"1\n";
16212 std::pair<AnsiString, TServiceCallingLocsList> AllServiceCallingLocsEntry;
16213 for(
unsigned int x = 0; x < TrainDataVectorCopy.size(); x++)
16218 ServiceCallingLocsList.clear();
16219 if(ActionVector.empty())
16223 if(ActionVector.at(0).SignallerControl)
16227 for(
unsigned int z = 0; z < ActionVector.size(); z++)
16245 int HLoc = TE.
HLoc;
16246 int VLoc = TE.
VLoc;
16247 AnsiString HString;
16248 AnsiString VString;
16251 HString = AnsiString(
'N') + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
16255 HString = AnsiString(HLoc);
16259 VString = AnsiString(
'N') + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
16263 VString = AnsiString(VLoc);
16265 ServiceCallingLocsList.push_back(HString +
'-' + VString);
16288 else if(AVE.
Command ==
"cdt")
16290 if(ActionVector.at(z-1).SequenceType ==
Start)
16294 else if(ActionVector.at(z+1).SequenceType ==
Finish)
16301 ServiceCallingLocsList.push_back(
"%%%" + TimeString);
16310 ServiceCallingLocsList.push_back(LName);
16314 int HLoc = TE.
HLoc;
16315 int VLoc = TE.
VLoc;
16316 AnsiString HString;
16317 AnsiString VString;
16320 HString = AnsiString(
'N') + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
16324 HString = AnsiString(HLoc);
16328 VString = AnsiString(
'N') + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
16332 VString = AnsiString(VLoc);
16334 ServiceCallingLocsList.push_back(HString +
'-' + VString);
16338 AllServiceCallingLocsEntry.second = ServiceCallingLocsList;
16342 SequenceLog +=
"2\n";
16372 ShowMessage(
"Unable to create a program-readable timetable - please check the timetable file validity");
16378 bool NumPlatsAtThisLocCalculated =
false, ArrivalsPrinted =
false, DeparturesPrinted =
false, AtLocsPrinted =
false;
16379 AnsiString PreviousService =
"", PreviousServiceAndRepeatNumTotalOutput =
"", BasicTime =
"", MinuteString =
"", LastAnsiTime =
"";
16380 int NumTrains = 0, NumPlats = 0, LastFrhCount = 0, FrhCount = 0, NumTrainsAtLoc = 0;
16382 SequenceLog +=
"3\n";
16384 for(
unsigned int x = 0; x < TrainDataVectorCopy.size(); x++)
16389 TDateTime LastTDTime;
16390 int IncMinutes = 0;
16392 if(ActionVector.empty())
16396 if(ActionVector.at(0).SignallerControl)
16400 if(AVLast->FormatType ==
Repeat)
16402 IncMinutes = ActionVector.at(ActionVector.size() - 1).RearStartOrRepeatMins;
16410 if(AVLast->ArrivalTime != TDateTime(-1))
16412 LastTDTime = AVLast->ArrivalTime;
16414 else if(AVLast->EventTime != TDateTime(-1))
16416 LastTDTime = AVLast->EventTime;
16435 SequenceLog +=
"4\n";
16467 for(
unsigned int x = 0; x < TrainDataVectorCopy.size(); x++)
16472 int IncMinutes = 0;
16474 if(ActionVector.empty())
16478 if(ActionVector.at(0).SignallerControl)
16482 if(ActionVector.at(ActionVector.size() - 1).FormatType ==
Repeat)
16484 IncMinutes = ActionVector.at(ActionVector.size() - 1).RearStartOrRepeatMins;
16486 for(
int y = 0; y < NumTrains; y++)
16500 for(
unsigned int z = 0; z < ActionVector.size(); z++)
16515 LocServiceTimesVector.push_back(TLSTEntry);
16518 AnsiString IncTime =
"", FoundStopTime =
"";
16519 for(
unsigned int a = z + 1; a < ActionVector.size(); a++)
16521 if(ActionVector.at(a).FormatType ==
TimeLoc)
16526 if(ActionVector.at(a).SequenceType ==
Finish)
16532 if(FoundStopTime ==
"")
16534 throw Exception(
"Failure to determine FoundStopTime for located Snt");
16536 int WhileCount = 0;
16545 if(IncTime >= FoundStopTime)
16549 LocServiceTimesVector.push_back(TLSTEntry);
16550 if(WhileCount > 2000)
16552 throw Exception(
"While loop failed to break in 2000 loops for located Snt");
16565 int HLoc = TE.
HLoc;
16566 int VLoc = TE.
VLoc;
16567 AnsiString HString;
16568 AnsiString VString;
16571 HString = AnsiString(
'N') + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
16575 HString = AnsiString(HLoc);
16579 VString = AnsiString(
'N') + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
16583 VString = AnsiString(VLoc);
16585 TLSTEntry.
Location = HString +
'-' + VString;
16589 LocServiceTimesVector.push_back(TLSTEntry);
16597 LocServiceTimesVector.push_back(TLSTEntry);
16599 AnsiString IncTime =
"", FoundStopTime =
"";
16600 for(
unsigned int a = z + 1; a < ActionVector.size(); a++)
16602 if(ActionVector.at(a).FormatType ==
TimeLoc)
16607 if(ActionVector.at(a).SequenceType ==
Finish)
16613 if(FoundStopTime ==
"")
16615 throw Exception(
"Failure to determine FoundStopTime for SequenceType == Start");
16617 int WhileCount = 0;
16626 if(IncTime >= FoundStopTime)
16630 LocServiceTimesVector.push_back(TLSTEntry);
16631 if(WhileCount > 2000)
16633 throw Exception(
"While loop failed to break in 2000 loops for SequenceType == Start");
16643 bool SkipAddingMinutes =
false;
16646 LocServiceTimesVector.push_back(TLSTEntry);
16648 AnsiString IncTime =
"", FoundStopTime =
"";
16649 for(
unsigned int a = z + 1; a < ActionVector.size(); a++)
16651 if(ActionVector.at(a).FormatType ==
TimeLoc)
16656 if(ActionVector.at(a).SequenceType ==
Finish)
16659 if((a <= (z + 2)) && (FoundStopTime == TLSTEntry.
ArrTime) && ((ActionVector.at(a).LinkedTrainEntryPtr > 0) || (ActionVector.at(a).NonRepeatingShuttleLinkEntryPtr > 0)))
16663 LocServiceTimesVector.pop_back();
16664 SkipAddingMinutes =
true;
16669 if(FoundStopTime ==
"")
16671 throw Exception(
"Failure to determine FoundStopTime for SequenceType == Start");
16673 if(!SkipAddingMinutes)
16675 int WhileCount = 0;
16684 if(IncTime >= FoundStopTime)
16688 LocServiceTimesVector.push_back(TLSTEntry);
16689 if(WhileCount > 2000)
16691 throw Exception(
"While loop failed to break in 2000 loops for SequenceType == Start");
16700 if((TLSTEntry.
Location == LocServiceTimesVector.back().Location) && (TLSTEntry.
ServiceAndRepeatNum == LocServiceTimesVector.back().ServiceAndRepeatNum))
16702 if(TLSTEntry.
DepTime == LocServiceTimesVector.back().ArrTime)
16704 TLSTEntry.
ArrTime = LocServiceTimesVector.back().ArrTime;
16705 LocServiceTimesVector.pop_back();
16706 LocServiceTimesVector.push_back(TLSTEntry);
16711 LocServiceTimesVector.push_back(TLSTEntry);
16717 LocServiceTimesVector.push_back(TLSTEntry);
16736 LocServiceTimesVector.push_back(TLSTEntry);
16740 AnsiString TempDepTime = TLSTEntry.
DepTime;
16742 LocServiceTimesVector.push_back(TLSTEntry);
16744 while(TLSTEntry.
AtLocTime < TempDepTime)
16749 TLSTEntry.
DepTime = TempDepTime;
16750 LocServiceTimesVector.push_back(TLSTEntry);
16754 LocServiceTimesVector.push_back(TLSTEntry);
16765 LocServiceTimesVector.push_back(TLSTEntry);
16768 LocServiceTimesVector.push_back(TLSTEntry);
16785 AnsiString HString;
16786 AnsiString VString;
16789 HString = AnsiString(
'N') + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
16793 HString = AnsiString(HLoc);
16797 VString = AnsiString(
'N') + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
16801 VString = AnsiString(VLoc);
16803 TLSTEntry.
Location = HString +
'-' + VString;
16805 LocServiceTimesVector.push_back(TLSTEntry);
16810 AnsiString FrhTime;
16811 if(ActionVector.at(z - 1).ArrivalTime != TDateTime(-1))
16815 else if(ActionVector.at(z - 1).EventTime != TDateTime(-1))
16823 LocServiceTimesVector.push_back(TLSTEntry);
16829 LocServiceTimesVector.push_back(TLSTEntry);
16834 else if(AVE.
Command ==
"Frh-sh")
16836 if(y == NumTrains - 1)
16842 LocServiceTimesVector.push_back(TLSTEntry);
16848 LocServiceTimesVector.push_back(TLSTEntry);
16861 SequenceLog +=
"5\n";
16889 TLocServiceTimesVector::iterator Ptr1, Ptr2;
16892 AnsiString TTFileName3 = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
16893 TTFileName3 = CurDir +
"\\Formatted timetables\\Conflict Analysis " + TTFileName3 +
"; " + RailwayTitle +
"; " + TimetableTitle +
".csv";
16895 std::ofstream TTFile3(TTFileName3.c_str());
16899 ShowMessage(
"Conflict Analysis file failed to open - can't be created");
16903 if(LocServiceTimesVector.empty())
16905 ShowMessage(
"No timetabled services found");
16907 DeleteFile(TTFileName3);
16911 TTFile3 <<
"Timetable analysis for timetable: '" + TimetableTitle +
"' in conjunction with railway: '" + RailwayTitle +
"'\n";
16912 TTFile3 <<
"See user manual or on-screen help section 5.12 for detailed information.\n\n\n";
16913 SequenceLog +=
"6\n";
16962 Ptr1 = LocServiceTimesVector.begin();
16964 while(Ptr2 != LocServiceTimesVector.end())
16966 while(Ptr2->Location == Ptr1->Location)
16969 if(Ptr2 == LocServiceTimesVector.end())
16976 if(Ptr2 != LocServiceTimesVector.end())
16984 TTFile3 <<
"Arrival & pass analysis: an asterisk means that the number of same approach code arrivals and passes is equal to or greater than the number of platforms.\n";
16985 TTFile3 <<
"If the total number of arrivals and passes at the same time exceeds the number of platforms the 'Trains present at location analysis' will show an asterisk.\n\n";
16986 MinuteString =
" minutes";
16987 AnsiString ServiceAndRepeatNumTotal =
"", ServiceAndRepeatNumTotalOutput =
"";
16990 MinuteString =
" minute";
16992 TTFile3 <<
"Location,Number of,Number of,Services arriving within " << AnsiString(ArrRange) << MinuteString <<
" with their arrival times and approach codes\n";
16993 TTFile3 <<
",Platforms,Trains\n\n";
16995 Ptr1 = LocServiceTimesVector.begin();
16997 while(Ptr2 != LocServiceTimesVector.end())
16999 PreviousService =
"";
17000 NumTrainsAtLoc = 0;
17001 ServiceAndRepeatNumTotal =
"";
17003 NumPlatsAtThisLocCalculated =
false;
17005 while((Ptr2->Location != Ptr1->Location) || ((Ptr1->Location ==
"") && (Ptr2->Location ==
"")))
17007 PreviousService =
"";
17008 NumTrainsAtLoc = 0;
17009 ServiceAndRepeatNumTotal =
"";
17011 NumPlatsAtThisLocCalculated =
false;
17015 if(Ptr2 == LocServiceTimesVector.end())
17020 if(Ptr2 == LocServiceTimesVector.end())
17024 while(Ptr2->Location == Ptr1->Location)
17026 PreviousService =
"";
17027 NumTrainsAtLoc = 0;
17028 ServiceAndRepeatNumTotal =
"";
17029 BasicTime = Ptr1->ArrTime;
17030 if((Ptr1->Location ==
"") && (Ptr2->Location ==
""))
17034 while(!
WithinTimeRange(0, BasicTime, Ptr2->ArrTime, ArrRange) || ((Ptr1->ArrTime ==
"") && (Ptr2->ArrTime ==
"")))
17036 BasicTime = Ptr2->ArrTime;
17039 if(Ptr2 == LocServiceTimesVector.end())
17043 if(Ptr2->Location != Ptr1->Location)
17048 if(Ptr2 == LocServiceTimesVector.end())
17052 if(Ptr2->Location != Ptr1->Location)
17058 if((Ptr1->ArrTime ==
"") && (Ptr2->ArrTime ==
""))
17062 if(!NumPlatsAtThisLocCalculated)
17065 NumPlatsAtThisLocCalculated =
true;
17067 if(Ptr1->ServiceAndRepeatNum != PreviousService)
17069 if(ServiceAndRepeatNumTotal ==
"")
17071 ServiceAndRepeatNumTotal = Ptr1->ServiceAndRepeatNum +
"," + Ptr1->ArrTime;
17072 NumTrainsAtLoc = 1;
17076 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr1->ServiceAndRepeatNum +
"," + Ptr1->ArrTime;
17079 PreviousService = Ptr2->ServiceAndRepeatNum;
17080 if(ServiceAndRepeatNumTotal ==
"")
17082 ServiceAndRepeatNumTotal = Ptr2->ServiceAndRepeatNum +
"," + Ptr2->ArrTime;
17083 NumTrainsAtLoc = 1;
17087 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr2->ServiceAndRepeatNum +
"," + Ptr2->ArrTime;
17091 if((Ptr2 == LocServiceTimesVector.end()) || (Ptr2->Location != Ptr1->Location) || (!
WithinTimeRange(2, BasicTime, Ptr2->ArrTime, ArrRange)))
17093 int MaxNumberOfSameDirections = 0;
17094 ServiceAndRepeatNumTotalOutput =
ConsolidateSARNTArrDep(1, ServiceAndRepeatNumTotal, NumTrainsAtLoc, Ptr1->Location,
true, AnalysisError, MaxNumberOfSameDirections);
17099 throw Exception(ServiceAndRepeatNumTotalOutput.c_str());
17103 AnsiString Asterisk =
"";
17104 if(MaxNumberOfSameDirections >= NumPlats)
17109 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << ServiceAndRepeatNumTotalOutput <<
'\n';
17110 ArrivalsPrinted =
true;
17111 ServiceAndRepeatNumTotal =
"";
17113 if(Ptr2 == LocServiceTimesVector.end())
17117 if(Ptr2->Location != Ptr1->Location)
17122 if(Ptr2 == LocServiceTimesVector.end())
17128 if(!ArrivalsPrinted)
17130 TTFile3 <<
"Nothing to report for arrivals";
17135 SequenceLog +=
"7\n";
17140 Ptr1 = LocServiceTimesVector.begin();
17142 while(Ptr2 != LocServiceTimesVector.end())
17144 while(Ptr2->Location == Ptr1->Location)
17147 if(Ptr2 == LocServiceTimesVector.end())
17154 if(Ptr2 != LocServiceTimesVector.end())
17161 TTFile3 <<
"Departure & pass analysis: an asterisk means that the number of same exit code departures and passes is equal to or greater than the number of platforms.\n";
17162 TTFile3 <<
"If the total number of departures and passes at the same time exceeds the number of platforms the 'Trains present at location analysis' will show an asterisk.\n\n";
17163 MinuteString =
" minutes";
17164 AnsiString ServiceAndRepeatNumTotal =
"", ServiceAndRepeatNumTotalOutput =
"";
17167 MinuteString =
" minute";
17169 TTFile3 <<
"Location,Number of,Number of,Services departing within " << AnsiString(DepRange) << MinuteString <<
" with their departure times and exit codes\n";
17170 TTFile3 <<
",Platforms,Trains\n\n";
17172 Ptr1 = LocServiceTimesVector.begin();
17174 while(Ptr2 != LocServiceTimesVector.end())
17176 PreviousService =
"";
17177 NumTrainsAtLoc = 0;
17178 ServiceAndRepeatNumTotal =
"";
17180 NumPlatsAtThisLocCalculated =
false;
17182 while((Ptr2->Location != Ptr1->Location) || ((Ptr1->Location ==
"") && (Ptr2->Location ==
"")))
17184 PreviousService =
"";
17185 NumTrainsAtLoc = 0;
17186 ServiceAndRepeatNumTotal =
"";
17188 NumPlatsAtThisLocCalculated =
false;
17192 if(Ptr2 == LocServiceTimesVector.end())
17197 if(Ptr2 == LocServiceTimesVector.end())
17201 while(Ptr2->Location == Ptr1->Location)
17203 PreviousService =
"";
17204 NumTrainsAtLoc = 0;
17205 ServiceAndRepeatNumTotal =
"";
17206 BasicTime = Ptr1->DepTime;
17207 if((Ptr1->Location ==
"") && (Ptr2->Location ==
""))
17211 while(!
WithinTimeRange(3, BasicTime, Ptr2->DepTime, DepRange) || ((Ptr1->DepTime ==
"") && (Ptr2->DepTime ==
"")))
17213 BasicTime = Ptr2->DepTime;
17216 if(Ptr2 == LocServiceTimesVector.end())
17220 if(Ptr2->Location != Ptr1->Location)
17225 if(Ptr2 == LocServiceTimesVector.end())
17229 if(Ptr2->Location != Ptr1->Location)
17235 if((Ptr1->DepTime ==
"") && (Ptr2->DepTime ==
""))
17239 if(!NumPlatsAtThisLocCalculated)
17242 NumPlatsAtThisLocCalculated =
true;
17244 if(Ptr1->ServiceAndRepeatNum != PreviousService)
17246 if(ServiceAndRepeatNumTotal ==
"")
17248 ServiceAndRepeatNumTotal = Ptr1->ServiceAndRepeatNum +
"," + Ptr1->DepTime;
17249 NumTrainsAtLoc = 1;
17253 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr1->ServiceAndRepeatNum +
"," + Ptr1->DepTime;
17256 PreviousService = Ptr2->ServiceAndRepeatNum;
17257 if(ServiceAndRepeatNumTotal ==
"")
17259 ServiceAndRepeatNumTotal = Ptr2->ServiceAndRepeatNum +
"," + Ptr2->DepTime;
17260 NumTrainsAtLoc = 1;
17264 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr2->ServiceAndRepeatNum +
"," + Ptr2->DepTime;
17268 if((Ptr2 == LocServiceTimesVector.end()) || (Ptr2->Location != Ptr1->Location) || (!
WithinTimeRange(5, BasicTime, Ptr2->DepTime, DepRange)))
17270 int MaxNumberOfSameDirections = 0;
17271 ServiceAndRepeatNumTotalOutput =
ConsolidateSARNTArrDep(3, ServiceAndRepeatNumTotal, NumTrainsAtLoc, Ptr1->Location,
false, AnalysisError, MaxNumberOfSameDirections);
17276 throw Exception(ServiceAndRepeatNumTotalOutput.c_str());
17280 AnsiString Asterisk =
"";
17281 if(MaxNumberOfSameDirections >= NumPlats)
17286 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << ServiceAndRepeatNumTotalOutput <<
'\n';
17287 DeparturesPrinted =
true;
17288 ServiceAndRepeatNumTotal =
"";
17290 if(Ptr2 == LocServiceTimesVector.end())
17294 if(Ptr2->Location != Ptr1->Location)
17299 if(Ptr2 == LocServiceTimesVector.end())
17305 if(!DeparturesPrinted)
17307 TTFile3 <<
"Nothing to report for departures";
17312 SequenceLog +=
"8\n";
17319 Ptr1 = LocServiceTimesVector.begin();
17321 while(Ptr2 != LocServiceTimesVector.end())
17323 while(Ptr2->Location == Ptr1->Location)
17326 if(Ptr2 == LocServiceTimesVector.end())
17333 if(Ptr2 != LocServiceTimesVector.end())
17340 TTFile3 <<
"Trains present at location analysis: an asterisk means that the number of trains at the location is greater than the number of platforms.\n\n";
17341 TTFile3 <<
"Location,Number of,Number of,Time,Services at the location at that time\n";
17342 TTFile3 <<
",Platforms,Trains,\n\n";
17343 AnsiString ServiceAndRepeatNumTotal =
"", ServiceAndRepeatNumTotalOutput =
"";
17344 Ptr1 = LocServiceTimesVector.begin();
17346 while(Ptr2 != LocServiceTimesVector.end())
17348 PreviousService =
"";
17349 ServiceAndRepeatNumTotal =
"";
17350 NumTrainsAtLoc = 0;
17352 NumPlatsAtThisLocCalculated =
false;
17354 while((Ptr2->Location != Ptr1->Location) || ((Ptr1->Location ==
"") && (Ptr2->Location ==
"")))
17356 PreviousService =
"";
17357 ServiceAndRepeatNumTotal =
"";
17358 NumTrainsAtLoc = 0;
17360 NumPlatsAtThisLocCalculated =
false;
17364 if(Ptr2 == LocServiceTimesVector.end())
17369 if(Ptr2 == LocServiceTimesVector.end())
17373 while(Ptr2->Location == Ptr1->Location)
17375 if(Ptr1->FrhMarker ==
"Frh")
17378 Ptr1->FrhMarker =
"FrhCounted";
17380 PreviousService =
"";
17381 NumTrainsAtLoc = 0;
17382 ServiceAndRepeatNumTotal =
"";
17383 if((Ptr1->Location ==
"") && (Ptr2->Location ==
""))
17387 while((Ptr2->AtLocTime != Ptr1->AtLocTime) || ((Ptr1->AtLocTime ==
"") && (Ptr2->AtLocTime ==
"")))
17390 if(Ptr1->FrhMarker ==
"Frh")
17393 Ptr1->FrhMarker =
"FrhCounted";
17396 if(Ptr2 == LocServiceTimesVector.end())
17400 if(Ptr2->Location != Ptr1->Location)
17405 if(Ptr2 == LocServiceTimesVector.end())
17409 if(Ptr2->Location != Ptr1->Location)
17413 while(Ptr2->AtLocTime == Ptr1->AtLocTime)
17415 if((Ptr1->AtLocTime ==
"") && (Ptr2->AtLocTime ==
""))
17419 if(!NumPlatsAtThisLocCalculated)
17422 NumPlatsAtThisLocCalculated =
true;
17424 if(Ptr1->ServiceAndRepeatNum != PreviousService)
17426 if(ServiceAndRepeatNumTotal ==
"")
17428 ServiceAndRepeatNumTotal = Ptr1->ServiceAndRepeatNum;
17429 NumTrainsAtLoc = 1;
17433 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr1->ServiceAndRepeatNum;
17436 PreviousService = Ptr2->ServiceAndRepeatNum;
17437 if(ServiceAndRepeatNumTotal ==
"")
17439 ServiceAndRepeatNumTotal = Ptr2->ServiceAndRepeatNum;
17440 NumTrainsAtLoc = 1;
17444 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr2->ServiceAndRepeatNum;
17447 if(Ptr1->FrhMarker ==
"Frh")
17450 Ptr1->FrhMarker =
"FrhCounted";
17453 if((Ptr2 == LocServiceTimesVector.end()) || (Ptr2->Location != Ptr1->Location) || (Ptr2->AtLocTime != Ptr1->AtLocTime))
17457 ServiceAndRepeatNumTotalOutput =
ConsolidateSARNTAtLoc(1, ServiceAndRepeatNumTotal, NumTrainsAtLoc);
17459 if((NumTrainsAtLoc > 1) && ((FrhCount < NumTrainsAtLoc) || (FrhCount != LastFrhCount)))
17461 AnsiString Asterisk =
"";
17462 if(NumTrainsAtLoc > NumPlats)
17469 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << Ptr1->AtLocTime <<
"," << ServiceAndRepeatNumTotalOutput <<
'\n';
17471 else if(FrhCount == 1)
17473 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << Ptr1->AtLocTime <<
" (1 remains here)," << ServiceAndRepeatNumTotalOutput <<
'\n';
17477 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << Ptr1->AtLocTime <<
" (" << FrhCount <<
" remain here)," << ServiceAndRepeatNumTotalOutput <<
'\n';
17479 LastFrhCount = FrhCount;
17480 PreviousServiceAndRepeatNumTotalOutput = ServiceAndRepeatNumTotalOutput;
17481 AtLocsPrinted =
true;
17482 ServiceAndRepeatNumTotal =
"";
17485 if(Ptr2 == LocServiceTimesVector.end())
17489 if(Ptr2->Location != Ptr1->Location)
17494 if(Ptr2 == LocServiceTimesVector.end())
17502 TTFile3 <<
"Nothing to report for trains at locations";
17507 SequenceLog +=
"9\n";
17537 TTrainDataEntry SingleServiceEntry, PartServiceEntry, NewPartServiceEntry, TempEntry;
17542 TTFile3 <<
"Train direction analysis - consisting of train facing directions on creation and possible missing or questionable changes of direction:\n\n";
17543 for(
unsigned int x = 0; x < TrainDataVectorCopy.size(); x++)
17551 if((AV.at(0).Command ==
"Snt") || (AV.at(0).Command ==
"Snt-sh"))
17553 SingleServiceEntry = TDE;
17555 for(
unsigned int y = 0; y < SSAV.size(); y++)
17557 if((SSAV.at(y).Command ==
"Fjo") || (SSAV.at(y).Command ==
"Frh") || (SSAV.at(y).Command ==
"Fer") || (SSAV.at(y).Command ==
"Frh-sh"))
17559 SingleServiceVector.push_back(SingleServiceEntry);
17562 else if((SSAV.at(y).Command ==
"fsp") || (SSAV.at(y).Command ==
"rsp"))
17564 PartServiceEntry = TDE;
17566 for(
unsigned int z = 0; z <= y; z++)
17571 PartServiceEntry.
ActionVector.at(z).Command =
"chr-sp";
17572 PartServiceEntry.
ActionVector.at(z).OtherHeadCode = PartServiceEntry.
ActionVector.at(z).LinkedTrainEntryPtr->ServiceReference;
17575 PartServiceVector.push_back(PartServiceEntry);
17576 if(SSAV.at(y).Command ==
"fsp")
17578 SSAV.at(y).Command =
"Front split - original service continues below";
17579 SSAV.at(y).OtherHeadCode =
"";
17581 if(SSAV.at(y).Command ==
"rsp")
17583 SSAV.at(y).Command =
"Rear split - original service continues below";
17584 SSAV.at(y).OtherHeadCode =
"";
17588 else if(SSAV.at(y).Command ==
"Fns")
17590 SSAV.at(y).Command =
"chr-Fns";
17591 SSAV.at(y).OtherHeadCode = SSAV.at(y).LinkedTrainEntryPtr->ServiceReference;
17592 PartServiceVector.push_back(SingleServiceEntry);
17595 else if(SSAV.at(y).Command ==
"Fns-sh")
17597 SSAV.at(y).Command =
"chr-Fns-sh";
17598 SSAV.at(y).OtherHeadCode = SSAV.at(y).NonRepeatingShuttleLinkEntryPtr->ServiceReference;
17599 SSAV.at(y).NonRepeatingShuttleLinkHeadCode =
"";
17600 PartServiceVector.push_back(SingleServiceEntry);
17603 else if(SSAV.at(y).Command ==
"F-nshs")
17605 SSAV.at(y).Command =
"chr-F-nshs";
17606 SSAV.at(y).OtherHeadCode = SSAV.at(y).LinkedTrainEntryPtr->ServiceReference;
17607 SSAV.at(y).NonRepeatingShuttleLinkHeadCode =
"";
17608 PartServiceVector.push_back(SingleServiceEntry);
17614 SequenceLog +=
"10\n";
17618 AnsiString NextRef;
17619 while(!PartServiceVector.empty())
17621 PartServiceEntry = PartServiceVector.at(0);
17622 for(
unsigned int y = 0; y < PartServiceEntry.
ActionVector.size(); y++)
17624 if(PartServiceEntry.
ActionVector.at(y).Command.SubString(1,3) ==
"chr")
17626 NextRef = PartServiceEntry.
ActionVector.at(y).OtherHeadCode;
17630 bool FinishType =
true, FoundFlag =
false;
17637 for(
unsigned int y = 1; y < TempEntry.
ActionVector.size(); y++)
17641 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
17645 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
17651 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
17652 SingleServiceVector.push_back(PartServiceVector.at(0));
17653 PartServiceVector.erase(&PartServiceVector.at(0));
17658 NewPartServiceEntry = PartServiceVector.at(0);
17662 PartServiceVector.push_back(NewPartServiceEntry);
17665 TempEntry.
ActionVector.at(y).Command =
"Front split - original service continues below";
17670 TempEntry.
ActionVector.at(y).Command =
"Rear split - original service continues below";
17673 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
17675 else if(TempEntry.
ActionVector.at(y).Command ==
"Fns")
17678 NextRef = TempEntry.
ActionVector.at(y).LinkedTrainEntryPtr->ServiceReference;
17680 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
17683 else if(TempEntry.
ActionVector.at(y).Command ==
"Fns-sh")
17686 TempEntry.
ActionVector.at(y).OtherHeadCode = TempEntry.
ActionVector.at(y).NonRepeatingShuttleLinkEntryPtr->ServiceReference;
17687 TempEntry.
ActionVector.at(y).NonRepeatingShuttleLinkHeadCode =
"";
17688 NextRef = TempEntry.
ActionVector.at(y).NonRepeatingShuttleLinkEntryPtr->ServiceReference;
17689 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
17692 else if(TempEntry.
ActionVector.at(y).Command ==
"F-nshs")
17696 TempEntry.
ActionVector.at(y).NonRepeatingShuttleLinkHeadCode =
"";
17697 NextRef = TempEntry.
ActionVector.at(y).LinkedTrainEntryPtr->ServiceReference;
17698 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
17706 SequenceLog += +
"11\n";
17707 throw Exception(
"Unable to find service reference " + NextRef +
" Last ref checked = " + TempEntry.
ServiceReference);
17711 if(!PartServiceVector.empty())
17713 SequenceLog +=
"12\n";
17714 throw Exception(
"PartServiceVector should be empty here - size = " + PartServiceVector.size());
17716 SequenceLog +=
"13\n";
17761 bool BufferFacingUnReportedFlag =
true;
17762 for(
unsigned int x = 0; x < SingleServiceVector.size(); x++)
17768 SequenceLog +=
"13a\n";
17769 throw Exception(
"Repeat entry present in SingleServiceVector at position " + x);
17772 if((AV.at(0).Command ==
"Snt") || (AV.at(0).Command ==
"Snt-sh"))
17774 bool BufferFlag =
false;
17775 int FrontTVPos = AV.at(0).FrontStartOrRepeatDigits;
17776 int RearTVPos = AV.at(0).RearStartOrRepeatMins;
17777 AnsiString FrontLocName = AV.at(0).LocationName;
17778 int NextEntryPos, NextExitPos;
17781 if(ThisElement.
Conn[0] == RearTVPos)
17785 else if(ThisElement.
Conn[1] == RearTVPos)
17789 else if(ThisElement.
Conn[2] == RearTVPos)
17793 else if(ThisElement.
Conn[3] == RearTVPos)
17805 if(ThisElement.
Conn[ThisExitPos] == -1)
17807 SequenceLog =
"13b\n";
17808 throw Exception(
"ThisElement connects to -1 for " + TDE.
ServiceReference);
17811 NextEntryPos = ThisElement.
ConnLinkPos[ThisExitPos];
17812 if((NextElement.
TrackType ==
Points) && ((NextEntryPos == 0) || (NextEntryPos == 2)))
17814 BufferFlag =
false;
17819 BufferFlag =
false;
17824 BufferFlag =
false;
17832 else if((NextElement.
TrackType ==
Points) && ((NextEntryPos == 1) || (NextEntryPos == 3)))
17834 ThisElement = NextElement;
17840 if(NextEntryPos == 0)
17844 else if(NextEntryPos == 1)
17848 else if(NextEntryPos == 2)
17852 else if(NextEntryPos == 3)
17857 ThisElement = NextElement;
17858 ThisExitPos = NextExitPos;
17863 if(BufferFacingUnReportedFlag)
17865 TTFile3 <<
"Train facing direction on creation analysis:-\n\n";
17866 BufferFacingUnReportedFlag =
false;
17868 TTFile3 <<
"Service " + TDE.
ServiceReference +
" facing buffers on creation\n";
17872 if(BufferFacingUnReportedFlag)
17874 TTFile3 <<
"Nothing to report for train facing directions\n\n";
17880 SequenceLog +=
"13c\n";
17883 AnsiString LocationNameToBeChecked =
"";
17884 bool MissingcdtUnreportedFlag =
true;
17886 for(
unsigned int x = 0; x < SingleServiceVector.size(); x++)
17889 unsigned int y = 0;
17890 int FirstInstance = 9999, SecondInstance = 9999;
17891 bool FullBreak =
false;
17892 MarkerList.clear();
17899 while((y < TDEntry.
ActionVector.size()) && !FullBreak)
17908 LocationNameToBeChecked = TDEntry.
ActionVector.at(y).LocationName;
17910 for(
unsigned int z = y; z < TDEntry.
ActionVector.size(); z++)
17915 (AVEntry.
Command ==
"Frh-sh"))
17930 for(
unsigned int a = z; a < TDEntry.
ActionVector.size(); a++)
17936 if(TDEntry.
ActionVector.at(a).LocationName == LocationNameToBeChecked)
17938 SecondInstance = a;
17940 for(
unsigned int b = 0; b < TDEntry.
ActionVector.size(); b++)
17942 if(TDEntry.
ActionVector.at(b).Command.SubString(1,3) ==
"chr")
17944 Sequence = Sequence + AnsiString(
" -> ") + TDEntry.
ActionVector.at(b).OtherHeadCode;
17947 if(MissingcdtUnreportedFlag)
17949 TTFile3 <<
"Possibly missing changes of direction - these will be missing unless the service travels in a loop back to the locations marked:-\n\n";
17951 TTFile3 << LocationNameToBeChecked <<
" is listed twice with no direction change between in service sequence: " << Sequence <<
"\n\n";
17952 MarkerList.push_back(FirstInstance);
17953 MarkerList.push_back(SecondInstance);
17955 MissingcdtUnreportedFlag =
false;
17966 if(MissingcdtUnreportedFlag)
17968 TTFile3 <<
"Nothing to report for missing changes of direction\n\n";
17974 SequenceLog +=
"14\n";
17983 typedef std::list<AnsiString> TLocList;
17984 TLocList BackwardList, ForwardList;
17985 bool IntroLineNeeded =
true;
17986 for(
unsigned int x = 0; x < SingleServiceVector.size(); x++)
17988 unsigned int cdtPosition = 9999;
17989 AnsiString cdtLocation =
"";
17990 bool FoundSameName =
false;
17991 MarkerList.clear();
17993 for(
unsigned int y = 0; y < TDEntry.
ActionVector.size(); y++)
17996 BackwardList.clear();
17997 ForwardList.clear();
18001 (AVEntry.
Command ==
"Frh-sh"))
18003 if(MarkerList.empty())
18010 for(
unsigned int b = 0; b < TDEntry.
ActionVector.size(); b++)
18012 if(TDEntry.
ActionVector.at(b).Command.SubString(1,3) ==
"chr")
18014 Sequence = Sequence + AnsiString(
" -> ") + TDEntry.
ActionVector.at(b).OtherHeadCode;
18018 if(IntroLineNeeded)
18020 TTFile3 <<
"Questionable change of direction analysis.\n\n";
18021 TTFile3 <<
"For marked changes of direction there are no same-name locations listed both above and below.\n";
18022 TTFile3 <<
"These changes of direction are probably valid for movements to and from depots but all should be checked to\n";
18023 TTFile3 <<
"make sure that none has been included incorrectly:\n\n";
18024 IntroLineNeeded =
false;
18026 TTFile3 <<
"Service sequence " << Sequence <<
" contains questionable changes of direction:-\n\n";
18038 for(
int z = y - 1; z >= 0; z--)
18041 if(AVEntry2.
Command ==
"cdt")
18050 BackwardList.sort();
18051 BackwardList.unique();
18052 for(
unsigned int z = y + 1; z < TDEntry.
ActionVector.size(); z++)
18066 ForwardList.sort();
18067 ForwardList.unique();
18068 FoundSameName =
false;
18070 if(!BackwardList.empty() && !ForwardList.empty())
18072 for(TLocList::iterator BLIt = BackwardList.begin(); BLIt != BackwardList.end(); BLIt++)
18074 for(TLocList::iterator FLIt = ForwardList.begin(); FLIt != ForwardList.end(); FLIt++)
18078 FoundSameName =
true;
18085 MarkerList.push_back(cdtPosition);
18089 if(IntroLineNeeded)
18091 TTFile3 <<
"Nothing to report for questionable changes of direction\n\n";
18107 SequenceLog +=
"15\n";
18113 catch(
const Exception &e)
18115 AnsiString TTErrorFileName =
"Analysis Error.txt";
18116 TTErrorFileName = CurDir +
"\\Formatted timetables\\" + TTErrorFileName;
18117 std::ofstream TTError(TTErrorFileName.c_str());
18120 ShowMessage(
"Analysis error file failed to open - can't be created");
18124 AnsiString TimeNow = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
18125 TTError << TimeNow.c_str() <<
'\n' << ArrRange <<
'\n' << ArrChecked <<
'\n' << DepRange <<
'\n' <<
18126 DepChecked <<
'\n' << AtLocChecked <<
'\n' << SequenceLog <<
'\n' << AnsiString(e.Message);
18129 ShowMessage(
"Error in Conflict Analysis: A file called 'Analysis Error.txt' has been created in your Formatted timetables folder. Please send this file together with your railway and timetable files to railwayfeedback@gmail.com for investigation - many thanks");
18139 if((SSVectorNumber < 0) || ((
unsigned int)SSVectorNumber >= SingleServiceVector.size()))
18141 throw Exception(
"SSVectorNumber out of range, = " + AnsiString(SSVectorNumber) +
", Vector size = " + SingleServiceVector.size());
18143 TTrainDataEntry SingleService = SingleServiceVector.at(SSVectorNumber);
18145 VecFile <<
",Initial service reference " << SingleService.
ServiceReference +
'\n';
18146 AnsiString Marker =
"";
18147 for(
unsigned int x = 0; x < SingleService.
ActionVector.size(); x++)
18150 for(
TNumListIterator MLIt = MarkerList.begin(); MLIt != MarkerList.end(); MLIt++)
18152 if(
int(x) == *MLIt)
18163 VecFile << Marker << AnsiString(AVE.
EventTime.TimeString()) <<
' ' << AVE.
Command <<
' ' << RearID <<
' ' << FrontID <<
'\n';
18169 VecFile << Marker << AnsiString(AVE.
EventTime.TimeString()) <<
' ' << AVE.
Command <<
' ' << RearID <<
' ' << FrontID <<
' ' << AVE.
OtherHeadCode <<
'\n';
18182 if(AVE.
Command.SubString(1,3) ==
"chr")
18191 AVE.
Command =
"Change of service to ";
18193 if(AVE.
Command.SubString(5, AVE.
Command.Length() - 4) ==
"Fns-sh")
18195 AVE.
Command =
"Change to shuttle finishing service";
18197 if(AVE.
Command.SubString(5, AVE.
Command.Length() - 4) ==
"F-nshs")
18220 VecFile << Marker << AnsiString(AVE.
EventTime.TimeString()) <<
' ' <<
"Pass" <<
' ' << AVE.
LocationName <<
'\n';
18224 AnsiString ListOfExits =
"";
18229 VecFile << Marker << AnsiString(AVE.
EventTime.TimeString()) <<
" Fer " << ListOfExits <<
'\n';
18233 VecFile << Marker <<
"Frh" <<
'\n';
18248 for(
unsigned int x = 0; x < Vector.size(); x++)
18252 if(Vector.at(x).ActionVector.at(Vector.at(x).ActionVector.size() - 1).FormatType ==
Repeat)
18254 TActionVectorEntry AVE = Vector.at(x).ActionVector.at(Vector.at(x).ActionVector.size() - 2);
18257 FinishType =
false;
18262 TActionVectorEntry AVE = Vector.at(x).ActionVector.at(Vector.at(x).ActionVector.size() - 1);
18265 FinishType =
false;
18270 return(Vector.at(x));
18274 return(Vector.at(Vector.size() - 1));
18283 if((Time1 ==
"") || (Time2 ==
""))
18288 int Mins = Time1.SubString(4,2).ToInt();
18289 int Hours = Time1.SubString(1,2).ToInt();
18290 int Time1Mins = (Hours * 60) + Mins;
18291 Mins = Time2.SubString(4,2).ToInt();
18292 Hours = Time2.SubString(1,2).ToInt();
18293 int Time2Mins = (Hours * 60) + Mins;
18294 if(abs(Time1Mins - Time2Mins) <= MinuteRange)
18306 bool &AnalysisError,
int &MaxNumberOfSameDirections)
18313 AnsiString Output =
"", OneService =
"", TempStr1 =
"", TempStr2 =
"";
18315 std::list<AnsiString> ServiceList;
18317 bool EvenComma =
false;
18318 for(
int x = 1; x <= Input.Length(); x++)
18320 TempStr1 = Input[x];
18321 if(TempStr1 == AnsiString(
',') && EvenComma)
18327 TempStr2 += Input[x];
18329 if(TempStr1 == AnsiString(
','))
18331 EvenComma = !EvenComma;
18335 while(TempStr2.Length() > 0)
18337 SCPos = TempStr2.Pos(
';');
18340 OneService = TempStr2.SubString(1, SCPos - 1);
18341 ServiceList.push_back(OneService);
18342 TempStr2 = TempStr2.SubString(SCPos + 1, TempStr2.Length() - SCPos);
18346 ServiceList.push_back(TempStr2);
18350 ServiceList.sort();
18351 ServiceList.unique();
18352 NumTrainsAtLoc = ServiceList.size();
18355 int DirectionMarker = 0;
18357 std::list<AnsiString>::iterator SLIt, SLIt1, SLIt2, SLIt3;
18359 for(SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
18361 *SLIt = *SLIt +
"&0";
18363 SLIt3 = ServiceList.end();
18365 AnsiString ServiceRef1, ServiceRef2, AnsiTime1, AnsiTime2, RepeatInfo1, RepeatInfo2;
18366 int AmpersandPos, SpacePos, CommaPos1, CommaPos2, RepeatNum1, RepeatNum2;
18367 TAllServiceCallingLocsMap::iterator ASCLIt1, ASCLIt2;
18369 MaxNumberOfSameDirections = 0;
18370 int SameDirectionCount = 0;
18372 for(std::list<AnsiString>::iterator SLIt1 = ServiceList.begin(); SLIt1 != SLIt3; SLIt1++)
18376 if(SLIt1->SubString(SLIt1->Length() - 1, 2) != AnsiString(
"&0"))
18382 CommaPos1 = SLIt1->Pos(
',');
18383 ServiceRef1 = SLIt1->SubString(1, CommaPos1 - 1);
18385 SpacePos = ServiceRef1.Pos(
' ');
18389 RepeatInfo1 = ServiceRef1.SubString(SpacePos + 2, ServiceRef1.Length() - SpacePos - 2);
18390 ServiceRef1 = ServiceRef1.SubString(1, SpacePos - 1);
18391 if(RepeatInfo1[1] ==
'F')
18397 SpacePos = RepeatInfo1.Pos(
' ');
18398 RepeatNum1 = RepeatInfo1.SubString(SpacePos + 1, RepeatInfo1.Length() - SpacePos).ToInt();
18401 AnsiTime1 = SLIt1->SubString(CommaPos1 + 1, SLIt1->Length() - CommaPos1);
18403 AmpersandPos = AnsiTime1.Pos(
'&');
18404 AnsiTime1 = AnsiTime1.SubString(1, AmpersandPos - 1);
18409 throw Exception(
"ASCLIt1 Error in " + Input);
18411 ServiceCallingLocsList1 = ASCLIt1->second;
18412 AmpersandPos = SLIt1->Pos(
'&');
18413 *SLIt1 = SLIt1->SubString(1, AmpersandPos);
18414 *SLIt1 = *SLIt1 + AnsiString(++DirectionMarker);
18416 SameDirectionCount = 1;
18417 for(SLIt2 = SLIt; SLIt2 != ServiceList.end(); SLIt2++)
18419 CommaPos2 = SLIt2->Pos(
',');
18420 ServiceRef2 = SLIt2->SubString(1, CommaPos2 - 1);
18422 SpacePos = ServiceRef2.Pos(
' ');
18426 RepeatInfo2 = ServiceRef2.SubString(SpacePos + 2, ServiceRef2.Length() - SpacePos - 2);
18427 ServiceRef2 = ServiceRef2.SubString(1, SpacePos - 1);
18428 if(RepeatInfo2[1] ==
'F')
18434 SpacePos = RepeatInfo2.Pos(
' ');
18435 RepeatNum2 = RepeatInfo2.SubString(SpacePos + 1, RepeatInfo2.Length() - SpacePos).ToInt();
18438 AnsiTime2 = SLIt2->SubString(CommaPos2 + 1, SLIt2->Length() - CommaPos2);
18440 AmpersandPos = AnsiTime2.Pos(
'&');
18441 AnsiTime2 = AnsiTime2.SubString(1, AmpersandPos - 1);
18446 throw Exception(
"ASCLIt2 Error in " + Input);
18448 ServiceCallingLocsList2 = ASCLIt2->second;
18450 if(
SameDirection(0, ServiceRef1, ServiceRef2, AnsiTime1, AnsiTime2, RepeatNum1, RepeatNum2, ServiceCallingLocsList1, ServiceCallingLocsList2, Location, Arrival))
18452 int AmpersandPos = SLIt2->Pos(
'&');
18453 *SLIt2 = SLIt2->SubString(1, AmpersandPos);
18454 *SLIt2 = *SLIt2 + AnsiString(DirectionMarker);
18455 SameDirectionCount++;
18458 if(SameDirectionCount > MaxNumberOfSameDirections)
18460 MaxNumberOfSameDirections = SameDirectionCount;
18465 if(SLIt3->SubString(SLIt3->Length() - 1, 2) == AnsiString(
"&0"))
18468 AmpersandPos = SLIt3->Pos(
'&');
18469 *SLIt3 = SLIt3->SubString(1, AmpersandPos);
18470 *SLIt3 = *SLIt3 + AnsiString(++DirectionMarker);
18473 for(SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
18476 AmpersandPos = SLIt->Pos(
'&');
18477 AnsiString DirectionMarkerString = SLIt->SubString(AmpersandPos + 1, SLIt->Length() - AmpersandPos);
18478 AnsiString ServiceWithoutMarker = SLIt->SubString(1, AmpersandPos - 1);
18479 DirectionMarker = DirectionMarkerString.ToInt();
18480 AnsiString DirectionSuffix =
"";
18482 if(DirectionMarker < 27)
18484 c = 64 + DirectionMarker;
18485 DirectionSuffix =
"," + AnsiString(c);
18487 else if(DirectionMarker < 53)
18489 c = 65 + DirectionMarker - 27;
18490 DirectionSuffix =
",A" + AnsiString(c);
18494 DirectionSuffix =
",?";
18496 *SLIt = ServiceWithoutMarker + DirectionSuffix;
18499 for(SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
18501 Output = Output + *SLIt +
",";
18503 if(Output.Length() > 0)
18505 Output = Output.SubString(1, Output.Length() - 1);
18511 catch(
const Exception &e)
18513 AnalysisError =
true;
18525 AnsiString InternalInput = Input, Output =
"", OneService =
"";
18527 std::list<AnsiString> ServiceList;
18529 while(InternalInput.Length() > 0)
18531 CommaPos = InternalInput.Pos(
',');
18534 OneService = InternalInput.SubString(1, CommaPos - 1);
18535 ServiceList.push_back(OneService);
18536 InternalInput = InternalInput.SubString(CommaPos + 1, InternalInput.Length() - CommaPos);
18540 ServiceList.push_back(InternalInput);
18541 InternalInput =
"";
18545 ServiceList.sort();
18546 ServiceList.unique();
18547 NumTrainsAtLoc = ServiceList.size();
18548 for(std::list<AnsiString>::iterator SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
18550 Output = Output + *SLIt +
",";
18552 if(Output.Length() > 0)
18554 Output = Output.SubString(1, Output.Length() - 1);
18567 AnsiString(RepeatNum1) +
"," + AnsiString(RepeatNum2) +
"," + Location);
18569 std::list<AnsiString>::iterator LP1 = 0, LP2 = 0, ListPtr1 = 0, ListPtr2 = 0, LocPtr1 = 0, LocPtr2 = 0;
18574 bool LocFound =
false;
18575 AnsiString Ref1 = Ref1In, Ref2 = Ref2In;
18577 TDateTime FirstServiceTime;
18580 int Ref1Target = 0, Ref1Count = 0;
18581 int SlashPos = Ref1.Pos(
'/');
18584 Ref1Target = Ref1.SubString(SlashPos + 1, Ref1.Length() - SlashPos).ToInt();
18585 Ref1 = Ref1.SubString(1, SlashPos - 1);
18587 int Ref2Target = 0, Ref2Count = 0;
18588 SlashPos = Ref2.Pos(
'/');
18591 Ref2Target = Ref2.SubString(SlashPos + 1, Ref2.Length() - SlashPos).ToInt();
18592 Ref2 = Ref2.SubString(1, SlashPos - 1);
18594 for(ListPtr1 = List1.begin(); ListPtr1 != List1.end(); ListPtr1++)
18597 if((*ListPtr1) == Location)
18599 LocPtr1 = ListPtr1;
18602 if(ListPtr1->SubString(1, 3) ==
"%%%")
18604 AnsiString CDTTime = ListPtr1->SubString(4, 5);
18609 FirstServiceTime = TDateTime(-1);
18610 bool BreakFlag =
false;
18613 if(TDVIt->ServiceReference == Ref1)
18615 if(Ref1Target > Ref1Count)
18620 IncMinutes = TDVIt->ActionVector.back().RearStartOrRepeatMins;
18621 for(TActionVector::iterator AVIt = TDVIt->ActionVector.begin(); AVIt != TDVIt->ActionVector.end(); AVIt++)
18625 FirstServiceTime = AVIt->EventTime;
18631 FirstServiceTime = AVIt->ArrivalTime;
18637 FirstServiceTime = AVIt->DepartureTime;
18648 if(IncMinutes == -1)
18650 throw Exception(
"Failed to find service for ServiceRef1 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
18652 if(FirstServiceTime == TDateTime(-1))
18654 throw Exception(
"Failed to find first service time for ServiceRef1 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
18658 if(!Arrival && (Time1 == CDTTime))
18663 if(Arrival && (Time1 == CDTTime))
18667 if(Time1 > CDTTime)
18672 if(Time1 < CDTTime)
18685 for(ListPtr2 = List2.begin(); ListPtr2 != List2.end(); ListPtr2++)
18687 if((*ListPtr2) == Location)
18689 LocPtr2 = ListPtr2;
18692 if(ListPtr2->SubString(1, 3) ==
"%%%")
18694 AnsiString CDTTime = ListPtr2->SubString(4, 5);
18699 FirstServiceTime = TDateTime(-1);
18700 bool BreakFlag =
false;
18703 if(TDVIt->ServiceReference == Ref2)
18705 if(Ref2Target > Ref2Count)
18710 IncMinutes = TDVIt->ActionVector.back().RearStartOrRepeatMins;
18711 for(TActionVector::iterator AVIt = TDVIt->ActionVector.begin(); AVIt != TDVIt->ActionVector.end(); AVIt++)
18715 FirstServiceTime = AVIt->EventTime;
18721 FirstServiceTime = AVIt->ArrivalTime;
18727 FirstServiceTime = AVIt->DepartureTime;
18738 if(IncMinutes == -1)
18740 throw Exception(
"IncMinutes -1 for ServiceRef2 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
18742 if(FirstServiceTime == TDateTime(-1))
18744 throw Exception(
"First service time -1 for ServiceRef2 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
18748 if(!Arrival && (Time2 == CDTTime))
18753 if(Arrival && (Time2 == CDTTime))
18757 if(Time2 > CDTTime)
18762 if(Time2 < CDTTime)
18777 LP1 = List1.begin();
18779 for(ListPtr1 = LocPtr1; ListPtr1 != LP1; ListPtr1--)
18781 if(ListPtr1 == List1.begin())
18785 if(ListPtr1->SubString(1, 3) ==
"%%%")
18792 LP2 = List2.begin();
18794 for(ListPtr2 = LocPtr2; ListPtr2 != LP2; ListPtr2--)
18796 if(ListPtr2 == List2.begin())
18800 if(ListPtr2->SubString(1, 3) ==
"%%%")
18810 for(ListPtr1 = LP1; ListPtr1 != List1.end(); ListPtr1++)
18812 if(ListPtr1 == LocPtr1)
18816 if(ListPtr1->SubString(1, 3) ==
"%%%")
18820 for(ListPtr2 = LP2; ListPtr2 != List2.end(); ListPtr2++)
18822 if(ListPtr2 == LocPtr2)
18826 if(ListPtr2->SubString(1, 3) ==
"%%%")
18830 if((*ListPtr1) == (*ListPtr2))
18847 for(ListPtr1 = LP1; ListPtr1 != List1.end(); ListPtr1++)
18849 if(ListPtr1 == List1.end())
18853 if(ListPtr1->SubString(1, 3) ==
"%%%")
18857 for(ListPtr2 = LP2; ListPtr2 != List2.end(); ListPtr2++)
18859 if(ListPtr2 == List2.end())
18863 if(ListPtr2->SubString(1, 3) ==
"%%%")
18867 if((*ListPtr1) == (*ListPtr2))
18884 if(ExitList.empty())
18890 AnsiString ExitLocList =
"";
18893 unsigned int Counter = 0;
18894 for(
TNumListIterator ELIt = ExitList.begin(); ELIt != ExitList.end(); ELIt++)
18898 if(((Counter % 6) == 0) && (Counter < (ExitList.size() - 1)))
18900 ExitLocList +=
"\n";
18903 if(StartName ==
"")
18905 if(ExitList.size() == 1)
18909 return(
" at " + ID);
18914 if(ExitList.size() < 4)
18916 AllowedExits =
",\nallowable exit element(s): " + ExitLocList;
18921 AllowedExits =
",\nallowable exit element(s):\n" + ExitLocList;
18926 for(
TNumListIterator ELIT = ExitList.begin(); ELIT != ExitList.end(); ELIT++)
18931 if(ExitList.size() < 4)
18933 AllowedExits =
",\nallowable exit element(s): " + ExitLocList;
18938 AllowedExits =
",\nallowable exit element(s):\n" + ExitLocList;
18944 if(ExitList.size() < 4)
18946 AllowedExits =
",\nallowable exit element(s): " + ExitLocList;
18947 return(
" at " + StartName);
18951 AllowedExits =
",\nallowable exit element(s):\n" + ExitLocList;
18952 return(
" at " + StartName);
18992 AnsiString FormatStr =
"####0.0";
18993 AnsiString AvLateArrMins =
"";
18994 AnsiString AvEarlyArrMins =
"";
18995 AnsiString AvLatePassMins =
"";
18996 AnsiString AvEarlyPassMins =
"";
18997 AnsiString AvLateDepMins =
"";
18998 AnsiString AvLateExitMins =
"";
18999 AnsiString AvEarlyExitMins =
"";
19029 PerfFile <<
'\n' <<
'\n' <<
"***************************************";
19030 PerfFile <<
'\n' <<
'\n' <<
"Performance summary:" <<
'\n';
19042 PerfFile <<
LateArrivals <<
" late arrivals (average " << AvLateArrMins.c_str() <<
" min)" <<
'\n';
19046 PerfFile <<
LateArrivals <<
" late arrival (" << AvLateArrMins.c_str() <<
" min)" <<
'\n';
19054 PerfFile <<
EarlyArrivals <<
" early arrivals (average " << AvEarlyArrMins.c_str() <<
" min)" <<
'\n';
19058 PerfFile <<
EarlyArrivals <<
" early arrival (" << AvEarlyArrMins.c_str() <<
" min)" <<
'\n';
19066 PerfFile <<
OnTimePasses <<
" on-time passes" <<
'\n';
19074 PerfFile <<
LatePasses <<
" late passes (average " << AvLatePassMins.c_str() <<
" min)" <<
'\n';
19078 PerfFile <<
LatePasses <<
" late pass (" << AvLatePassMins.c_str() <<
" min)" <<
'\n';
19082 PerfFile <<
LatePasses <<
" late passes" <<
'\n';
19086 PerfFile <<
EarlyPasses <<
" early passes (average " << AvEarlyPassMins.c_str() <<
" min)" <<
'\n';
19090 PerfFile <<
EarlyPasses <<
" early pass (" << AvEarlyPassMins.c_str() <<
" min)" <<
'\n';
19094 PerfFile <<
EarlyPasses <<
" early passes" <<
'\n';
19099 PerfFile <<
OnTimeExits <<
" on-time exits" <<
'\n';
19103 PerfFile <<
OnTimeExits <<
" on-time exit" <<
'\n';
19107 PerfFile <<
LateExits <<
" late exits (average " << AvLateExitMins.c_str() <<
" min)" <<
'\n';
19111 PerfFile <<
LateExits <<
" late exit (" << AvLateExitMins.c_str() <<
" min)" <<
'\n';
19115 PerfFile <<
LateExits <<
" late exits" <<
'\n';
19119 PerfFile <<
EarlyExits <<
" early exits (average " << AvEarlyExitMins.c_str() <<
" min)" <<
'\n';
19123 PerfFile <<
EarlyExits <<
" early exit (" << AvEarlyExitMins.c_str() <<
" min)" <<
'\n';
19127 PerfFile <<
EarlyExits <<
" early exits" <<
'\n';
19132 PerfFile <<
OnTimeDeps <<
" on-time departures" <<
'\n';
19136 PerfFile <<
OnTimeDeps <<
" on-time departure" <<
'\n';
19140 PerfFile <<
LateDeps <<
" late departures (average " << AvLateDepMins.c_str() <<
" min)" <<
'\n';
19144 PerfFile <<
LateDeps <<
" late departure (" << AvLateDepMins.c_str() <<
" min)" <<
'\n';
19148 PerfFile <<
LateDeps <<
" late departures" <<
'\n';
19150 TDateTime TempExcessLCDownTime;
19164 if(TempExcessLCDownTime > TDateTime(0))
19170 AnsiString FormattedExcessLCDownMins = FormatFloat(FormatStr,
ExcessLCDownMins);
19174 PerfFile << FormattedExcessLCDownMins.c_str() <<
" excess minutes of level crossing barrier down time" <<
'\n';
19178 PerfFile <<
MissedStops <<
" missed stops" <<
'\n';
19182 PerfFile <<
MissedStops <<
" missed stop" <<
'\n';
19218 PerfFile <<
NumFailures <<
" train failures" <<
'\n';
19222 PerfFile <<
NumFailures <<
" train failure" <<
'\n';
19228 PerfFile <<
AvHoursIntValue <<
" hour mean time betweeen train failures" <<
'\n';
19232 PerfFile <<
AvHoursIntValue <<
" hours mean time betweeen train failures" <<
'\n';
19235 AnsiString AvLateMinsLocsNotReached =
"";
19241 if(LocsNotReached > 0)
19244 PerfFile << LocsNotReached <<
" locations that trains failed to reach (average lateness " << AvLateMinsLocsNotReached.c_str() <<
" min)" <<
'\n';
19248 PerfFile <<
SPADRisks <<
" SPAD risks" <<
'\n';
19252 PerfFile <<
SPADRisks <<
" SPAD risk" <<
'\n';
19264 PerfFile <<
Derailments <<
" derailments" <<
'\n';
19268 PerfFile <<
Derailments <<
" derailment" <<
'\n';
19278 PerfFile <<
'\n' <<
"***************************************" <<
'\n';
19280 bool DerailSPADFlag =
false, CrashFlag =
false;
19282 int OverallScorePercent = 100;
19283 int TotArrDepExit = 0;
19284 double TotLateMinsFactor = 1;
19285 double MissedStopAndSPADRiskFactor = 1;
19286 double NetNegFactor = 1;
19296 OverallScorePercent = 5;
19297 DerailSPADFlag =
true;
19301 OverallScorePercent = 0;
19304 if(OverallScorePercent == 100)
19306 if(TotArrDepExit > 0)
19308 TotLateMinsFactor =
19316 NetNegFactor = TotLateMinsFactor * MissedStopAndSPADRiskFactor;
19318 OverallScorePercent = 100 * NetNegFactor;
19321 if((TotArrDepExit > 0) || DerailSPADFlag || CrashFlag)
19324 AnsiString OneFailureString =
", though the failure would account for some poor performance";
19325 AnsiString TwoOrMoreFailureString =
", though the failures would account for some poor performance";
19326 AnsiString AddedString =
"";
19329 AddedString = OneFailureString;
19333 AddedString = TwoOrMoreFailureString;
19335 PerfFile <<
"\nOverall score: " << OverallScorePercent <<
"%\n";
19336 AnsiString Rating =
"";
19337 if(OverallScorePercent == 100)
19339 Rating =
"Perfect!";
19341 else if(OverallScorePercent >= 95)
19343 Rating =
"Excellent";
19345 else if(OverallScorePercent >= 90)
19347 Rating =
"Very good";
19349 else if(OverallScorePercent >= 80)
19353 else if(OverallScorePercent >= 70)
19357 else if(OverallScorePercent >= 60)
19359 Rating =
"Unacceptable" + AddedString;
19361 else if(OverallScorePercent >= 50)
19363 Rating =
"Poor" + AddedString;
19365 else if(OverallScorePercent >= 40)
19367 Rating =
"Bad" + AddedString;
19369 else if(OverallScorePercent >= 30)
19371 Rating =
"Very bad" + AddedString;
19373 else if(OverallScorePercent >= 20)
19375 Rating =
"Terrible" + AddedString;
19377 else if(OverallScorePercent >= 10)
19379 Rating =
"Appalling" + AddedString;
19381 else if(OverallScorePercent >= 5)
19385 Rating =
"Disastrous - potential loss of life";
19390 Rating =
"Dire" + AddedString;
19393 else if(OverallScorePercent < 5)
19397 Rating =
"Catastrophic - loss of life";
19401 Rating =
"Abysmal";
19404 PerfFile <<
"Overall rating: " << Rating.c_str() <<
'\n';
19408 PerfFile <<
"\nThere were no timetabled departures, arrivals or exits so there is insufficient information to provide a performance score or rating" <<
'\n';
19410 PerfFile <<
'\n' <<
"***************************************";
19419 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
19469 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
19504 int IncrementalMinutes = 0;
19518 bool TrainOperatingFlag =
false;
19523 TrainOperatingFlag =
true;
19527 if(TrainOperatingFlag)
19535 for(
unsigned int z = 0; z < TDEntry.
ActionVector.size(); z++)
19582 AnsiString HeadCode;
19586 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
19590 HCandTrainPosParam.first = HeadCode;
19591 HCandTrainPosParam.second = TrainID;
19593 if((TimeToAct >= 0) && (TimeToAct < 59.9))
19596 OpTimeToActMultiMapEntry.first = TimeToAct;
19597 OpTimeToActMultiMapEntry.second = HCandTrainPosParam;
19626 float TimeToAct = 0;
19627 int DistanceToRedSignal = 0;
19630 ContinuationEntryVecPosVector.clear();
19631 bool LaterTrain =
false;
19635 LaterTrain =
false;
19636 if(CTEIt->second.TrainDataEntryPtr->TrainOperatingDataVector.at(CTEIt->second.RepeatNumber).RunningEntry !=
NotStarted)
19647 if(!ContinuationEntryVecPosVector.empty())
19649 for(
unsigned int x = 0; x < ContinuationEntryVecPosVector.size(); x++)
19651 if(CTEIt->second.VectorPosition == ContinuationEntryVecPosVector.at(x))
19665 ContinuationEntryVecPosVector.push_back(CTEIt->second.VectorPosition);
19666 AnsiString HeadCode = CTEIt->second.HeadCode;
19667 float CurrentStopTime;
19668 float LaterStopTime;
19669 float RecoverableTime;
19672 int DistanceToExit;
19674 bool SigControlAndCanPassRedSignal =
false;
19678 SigControlAndCanPassRedSignal, &CTEIt->second.TrainDataEntryPtr->ActionVector.at(0),
19680 HeadCode, TrainID, CurrentStopTime, LaterStopTime, RecoverableTime, AvTrackSpeed, DistanceToExit, ExitPair);
19683 if(AvTrackSpeed < 30)
19687 if(DistanceToRedSignal == -1)
19693 int Speed = AvTrackSpeed;
19694 int MaxSpeed = int(CTEIt->second.TrainDataEntryPtr->MaxRunningSpeed);
19695 if(AvTrackSpeed > MaxSpeed)
19699 if(CTEIt->second.TrainDataEntryPtr->ActionVector.at(0).SignallerControl)
19702 Speed = CTEIt->second.TrainDataEntryPtr->SignallerSpeed;
19705 TimeToAct = LaterStopTime + DistanceToRedSignal * 3.6 / 60 / Speed;
19710 float MinsBefEnter = double(CTEIt->first -
TTClockTime) * 86400.0 / 60.0;
19711 TimeToAct += MinsBefEnter;
19714 HCandTrainPosParam.first = HeadCode;
19715 HCandTrainPosParam.second = -1 - CTEIt->second.VectorPosition;
19718 if(TimeToAct < 59.9)
19720 OpTimeToActMultiMapEntry.first = TimeToAct;
19721 OpTimeToActMultiMapEntry.second = HCandTrainPosParam;
19746 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
19756 TimeToExitMultiMapEntry.first = ExitPair;
19757 TimeToExitMultiMapEntry.second = ExitInfo;
19767 bool SigControlAndCanPassRedSignal,
TActionVectorEntry *AVPtr, AnsiString HeadCode,
int TrainID,
float &CurrentStopTime,
float &LaterStopTime,
19768 float &RecoverableTime,
int &AvTrackSpeed,
int &DistanceToExit,
THVShortPair &ExitPair)
19777 AnsiString(TrackVectorPositionEntryPos) +
", " + AVPtr->
Command);
19778 int DistanceToRedSignal = 0;
19779 DistanceToExit = -1;
19780 ExitPair.first = -1;
19781 ExitPair.second = -1;
19782 int CumTrackSpeed = 0;
19784 int TrackSpeedCount = 0;
19785 float KmPerLocationStop;
19786 float MaxAllowableSpeed;
19796 int CurrentElement = TrackVectorPosition;
19797 int CurrentEntryPos = TrackVectorPositionEntryPos;
19802 CurrentStopTime = 0;
19804 RecoverableTime = 0;
19805 if(CurrentElement == -1)
19810 int CurrentExitPos;
19815 if((CurrentEntryPos == 0) || (CurrentEntryPos == 2))
19819 CurrentExitPos = 1;
19823 CurrentExitPos = 3;
19828 CurrentExitPos = 0;
19864 CurrentStopTime = float(TimeToDepart);
19870 if((CurrentExitConfig ==
Signal) && (CurrentAttribute == 0))
19881 else if(SigControlAndCanPassRedSignal)
19886 if((NextEntryPos == 0) || (NextEntryPos == 2))
19907 CurrentElement = NextElement;
19908 CurrentEntryPos = NextEntryPos;
19909 CurrentExitPos = NextExitPos;
19921 int LaterStopNumber = 0;
19925 while(!((CurrentExitConfig ==
Signal) && (CurrentAttribute == 0)))
19934 if(CurrentEntryPos > 1)
19949 DistanceToExit = DistanceToRedSignal;
19954 if(TrackSpeedCount > 0)
19956 MaxAllowableSpeed = CumTrackSpeed / TrackSpeedCount;
19960 if(CurrentEntryPos > 1)
19971 if(LaterStopNumber > 0)
19973 KmPerLocationStop = float(DistanceToRedSignal) / LaterStopNumber / 1000;
19974 AvTrackSpeed = (8.75 * KmPerLocationStop) + 44;
19980 AvTrackSpeed = (sqrt(
float(DistanceToRedSignal) / 1000) * 44) + 60;
19984 if(AvTrackSpeed > MaxAllowableSpeed)
19986 AvTrackSpeed = MaxAllowableSpeed;
19998 bool StopRequired =
false;
20015 int TrainOnElement;
20022 if(CurrentEntryPos > 1)
20031 if((TrainOnElement > -1) && (TrainOnElement != TrainID))
20040 double StopTimeDouble;
20053 if(StopTimeDouble < 0.5)
20055 StopTimeDouble = 0.5;
20059 LaterStopTime += float(StopTimeDouble);
20060 RecoverableTime += StopTimeDouble - 0.5;
20061 if((LaterStopNumber == 1) && (TrainID > -1))
20069 if((AVPtr + 1)->FormatType ==
TimeLoc)
20073 StopTimeDouble = double((AVPtr + 1)->DepartureTime - AVPtr->
ArrivalTime) * 86400.0 / 60.0;
20075 if(StopTimeDouble < 0.5)
20077 StopTimeDouble = 0.5;
20080 LaterStopTime += float(StopTimeDouble);
20081 RecoverableTime += StopTimeDouble - 0.5;
20082 if((LaterStopNumber == 1) && (TrainID > -1))
20098 if(NextElement == -1)
20107 if((NextEntryPos == 0) || (NextEntryPos == 2))
20128 CurrentElement = NextElement;
20129 CurrentEntryPos = NextEntryPos;
20130 CurrentExitPos = NextExitPos;
20134 if((CurrentExitConfig ==
Signal) && (CurrentAttribute == 0))
20147 if(TrackSpeedCount > 0)
20149 MaxAllowableSpeed = CumTrackSpeed / TrackSpeedCount;
20153 if(CurrentEntryPos > 1)
20164 if(LaterStopNumber > 0)
20166 KmPerLocationStop = float(DistanceToRedSignal) / LaterStopNumber / 1000;
20167 AvTrackSpeed = (8.75 * KmPerLocationStop) + 44;
20173 AvTrackSpeed = (sqrt(
float(DistanceToRedSignal) / 1000) * 44) + 60;
20177 if(AvTrackSpeed > MaxAllowableSpeed)
20179 AvTrackSpeed = MaxAllowableSpeed;
20182 return(DistanceToRedSignal);